PageRenderTime 59ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 3ms

/bootstrap/compiled.php

https://github.com/liamjay/basic-laravel-authentication
PHP | 10600 lines | 10510 code | 90 blank | 0 comment | 815 complexity | 256ff71a41db89c2226051e6eb6926ab MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. namespace Illuminate\Support;
  3. class ClassLoader
  4. {
  5. protected static $directories = array();
  6. protected static $registered = false;
  7. public static function load($class)
  8. {
  9. $class = static::normalizeClass($class);
  10. foreach (static::$directories as $directory) {
  11. if (file_exists($path = $directory . DIRECTORY_SEPARATOR . $class)) {
  12. require_once $path;
  13. return true;
  14. }
  15. }
  16. return false;
  17. }
  18. public static function normalizeClass($class)
  19. {
  20. if ($class[0] == '\\') {
  21. $class = substr($class, 1);
  22. }
  23. return str_replace(array('\\', '_'), DIRECTORY_SEPARATOR, $class) . '.php';
  24. }
  25. public static function register()
  26. {
  27. if (!static::$registered) {
  28. static::$registered = spl_autoload_register(array('\\Illuminate\\Support\\ClassLoader', 'load'));
  29. }
  30. }
  31. public static function addDirectories($directories)
  32. {
  33. static::$directories = array_merge(static::$directories, (array) $directories);
  34. static::$directories = array_unique(static::$directories);
  35. }
  36. public static function removeDirectories($directories = null)
  37. {
  38. if (is_null($directories)) {
  39. static::$directories = array();
  40. } else {
  41. $directories = (array) $directories;
  42. static::$directories = array_filter(static::$directories, function ($directory) use($directories) {
  43. return !in_array($directory, $directories);
  44. });
  45. }
  46. }
  47. public static function getDirectories()
  48. {
  49. return static::$directories;
  50. }
  51. }
  52. namespace Illuminate\Container;
  53. use Closure;
  54. use ArrayAccess;
  55. use ReflectionClass;
  56. use ReflectionParameter;
  57. class BindingResolutionException extends \Exception
  58. {
  59. }
  60. class Container implements ArrayAccess
  61. {
  62. protected $resolved = array();
  63. protected $bindings = array();
  64. protected $instances = array();
  65. protected $aliases = array();
  66. protected $reboundCallbacks = array();
  67. protected $resolvingCallbacks = array();
  68. protected $globalResolvingCallbacks = array();
  69. protected function resolvable($abstract)
  70. {
  71. return $this->bound($abstract) || $this->isAlias($abstract);
  72. }
  73. public function bound($abstract)
  74. {
  75. return isset($this[$abstract]) || isset($this->instances[$abstract]);
  76. }
  77. public function isAlias($name)
  78. {
  79. return isset($this->aliases[$name]);
  80. }
  81. public function bind($abstract, $concrete = null, $shared = false)
  82. {
  83. if (is_array($abstract)) {
  84. list($abstract, $alias) = $this->extractAlias($abstract);
  85. $this->alias($abstract, $alias);
  86. }
  87. $this->dropStaleInstances($abstract);
  88. if (is_null($concrete)) {
  89. $concrete = $abstract;
  90. }
  91. if (!$concrete instanceof Closure) {
  92. $concrete = $this->getClosure($abstract, $concrete);
  93. }
  94. $bound = $this->bound($abstract);
  95. $this->bindings[$abstract] = compact('concrete', 'shared');
  96. if ($bound) {
  97. $this->rebound($abstract);
  98. }
  99. }
  100. protected function getClosure($abstract, $concrete)
  101. {
  102. return function ($c, $parameters = array()) use($abstract, $concrete) {
  103. $method = $abstract == $concrete ? 'build' : 'make';
  104. return $c->{$method}($concrete, $parameters);
  105. };
  106. }
  107. public function bindIf($abstract, $concrete = null, $shared = false)
  108. {
  109. if (!$this->bound($abstract)) {
  110. $this->bind($abstract, $concrete, $shared);
  111. }
  112. }
  113. public function singleton($abstract, $concrete = null)
  114. {
  115. return $this->bind($abstract, $concrete, true);
  116. }
  117. public function share(Closure $closure)
  118. {
  119. return function ($container) use($closure) {
  120. static $object;
  121. if (is_null($object)) {
  122. $object = $closure($container);
  123. }
  124. return $object;
  125. };
  126. }
  127. public function bindShared($abstract, Closure $closure)
  128. {
  129. return $this->bind($abstract, $this->share($closure), true);
  130. }
  131. public function extend($abstract, Closure $closure)
  132. {
  133. if (!isset($this->bindings[$abstract])) {
  134. throw new \InvalidArgumentException("Type {$abstract} is not bound.");
  135. }
  136. if (isset($this->instances[$abstract])) {
  137. $this->instances[$abstract] = $closure($this->instances[$abstract], $this);
  138. $this->rebound($abstract);
  139. } else {
  140. $extender = $this->getExtender($abstract, $closure);
  141. $this->bind($abstract, $extender, $this->isShared($abstract));
  142. }
  143. }
  144. protected function getExtender($abstract, Closure $closure)
  145. {
  146. $resolver = $this->bindings[$abstract]['concrete'];
  147. return function ($container) use($resolver, $closure) {
  148. return $closure($resolver($container), $container);
  149. };
  150. }
  151. public function instance($abstract, $instance)
  152. {
  153. if (is_array($abstract)) {
  154. list($abstract, $alias) = $this->extractAlias($abstract);
  155. $this->alias($abstract, $alias);
  156. }
  157. unset($this->aliases[$abstract]);
  158. $bound = $this->bound($abstract);
  159. $this->instances[$abstract] = $instance;
  160. if ($bound) {
  161. $this->rebound($abstract);
  162. }
  163. }
  164. public function alias($abstract, $alias)
  165. {
  166. $this->aliases[$alias] = $abstract;
  167. }
  168. protected function extractAlias(array $definition)
  169. {
  170. return array(key($definition), current($definition));
  171. }
  172. public function rebinding($abstract, Closure $callback)
  173. {
  174. $this->reboundCallbacks[$abstract][] = $callback;
  175. if ($this->bound($abstract)) {
  176. return $this->make($abstract);
  177. }
  178. }
  179. public function refresh($abstract, $target, $method)
  180. {
  181. return $this->rebinding($abstract, function ($app, $instance) use($target, $method) {
  182. $target->{$method}($instance);
  183. });
  184. }
  185. protected function rebound($abstract)
  186. {
  187. $instance = $this->make($abstract);
  188. foreach ($this->getReboundCallbacks($abstract) as $callback) {
  189. call_user_func($callback, $this, $instance);
  190. }
  191. }
  192. protected function getReboundCallbacks($abstract)
  193. {
  194. if (isset($this->reboundCallbacks[$abstract])) {
  195. return $this->reboundCallbacks[$abstract];
  196. } else {
  197. return array();
  198. }
  199. }
  200. public function make($abstract, $parameters = array())
  201. {
  202. $abstract = $this->getAlias($abstract);
  203. $this->resolved[$abstract] = true;
  204. if (isset($this->instances[$abstract])) {
  205. return $this->instances[$abstract];
  206. }
  207. $concrete = $this->getConcrete($abstract);
  208. if ($this->isBuildable($concrete, $abstract)) {
  209. $object = $this->build($concrete, $parameters);
  210. } else {
  211. $object = $this->make($concrete, $parameters);
  212. }
  213. if ($this->isShared($abstract)) {
  214. $this->instances[$abstract] = $object;
  215. }
  216. $this->fireResolvingCallbacks($abstract, $object);
  217. return $object;
  218. }
  219. protected function getConcrete($abstract)
  220. {
  221. if (!isset($this->bindings[$abstract])) {
  222. if ($this->missingLeadingSlash($abstract) && isset($this->bindings['\\' . $abstract])) {
  223. $abstract = '\\' . $abstract;
  224. }
  225. return $abstract;
  226. } else {
  227. return $this->bindings[$abstract]['concrete'];
  228. }
  229. }
  230. protected function missingLeadingSlash($abstract)
  231. {
  232. return is_string($abstract) && strpos($abstract, '\\') !== 0;
  233. }
  234. public function build($concrete, $parameters = array())
  235. {
  236. if ($concrete instanceof Closure) {
  237. return $concrete($this, $parameters);
  238. }
  239. $reflector = new ReflectionClass($concrete);
  240. if (!$reflector->isInstantiable()) {
  241. $message = "Target [{$concrete}] is not instantiable.";
  242. throw new BindingResolutionException($message);
  243. }
  244. $constructor = $reflector->getConstructor();
  245. if (is_null($constructor)) {
  246. return new $concrete();
  247. }
  248. $dependencies = $constructor->getParameters();
  249. $parameters = $this->keyParametersByArgument($dependencies, $parameters);
  250. $instances = $this->getDependencies($dependencies, $parameters);
  251. return $reflector->newInstanceArgs($instances);
  252. }
  253. protected function getDependencies($parameters, array $primitives = array())
  254. {
  255. $dependencies = array();
  256. foreach ($parameters as $parameter) {
  257. $dependency = $parameter->getClass();
  258. if (array_key_exists($parameter->name, $primitives)) {
  259. $dependencies[] = $primitives[$parameter->name];
  260. } elseif (is_null($dependency)) {
  261. $dependencies[] = $this->resolveNonClass($parameter);
  262. } else {
  263. $dependencies[] = $this->resolveClass($parameter);
  264. }
  265. }
  266. return (array) $dependencies;
  267. }
  268. protected function resolveNonClass(ReflectionParameter $parameter)
  269. {
  270. if ($parameter->isDefaultValueAvailable()) {
  271. return $parameter->getDefaultValue();
  272. } else {
  273. $message = "Unresolvable dependency resolving [{$parameter}].";
  274. throw new BindingResolutionException($message);
  275. }
  276. }
  277. protected function resolveClass(ReflectionParameter $parameter)
  278. {
  279. try {
  280. return $this->make($parameter->getClass()->name);
  281. } catch (BindingResolutionException $e) {
  282. if ($parameter->isOptional()) {
  283. return $parameter->getDefaultValue();
  284. } else {
  285. throw $e;
  286. }
  287. }
  288. }
  289. protected function keyParametersByArgument(array $dependencies, array $parameters)
  290. {
  291. foreach ($parameters as $key => $value) {
  292. if (is_numeric($key)) {
  293. unset($parameters[$key]);
  294. $parameters[$dependencies[$key]->name] = $value;
  295. }
  296. }
  297. return $parameters;
  298. }
  299. public function resolving($abstract, Closure $callback)
  300. {
  301. $this->resolvingCallbacks[$abstract][] = $callback;
  302. }
  303. public function resolvingAny(Closure $callback)
  304. {
  305. $this->globalResolvingCallbacks[] = $callback;
  306. }
  307. protected function fireResolvingCallbacks($abstract, $object)
  308. {
  309. if (isset($this->resolvingCallbacks[$abstract])) {
  310. $this->fireCallbackArray($object, $this->resolvingCallbacks[$abstract]);
  311. }
  312. $this->fireCallbackArray($object, $this->globalResolvingCallbacks);
  313. }
  314. protected function fireCallbackArray($object, array $callbacks)
  315. {
  316. foreach ($callbacks as $callback) {
  317. call_user_func($callback, $object, $this);
  318. }
  319. }
  320. public function isShared($abstract)
  321. {
  322. if (isset($this->bindings[$abstract]['shared'])) {
  323. $shared = $this->bindings[$abstract]['shared'];
  324. } else {
  325. $shared = false;
  326. }
  327. return isset($this->instances[$abstract]) || $shared === true;
  328. }
  329. protected function isBuildable($concrete, $abstract)
  330. {
  331. return $concrete === $abstract || $concrete instanceof Closure;
  332. }
  333. protected function getAlias($abstract)
  334. {
  335. return isset($this->aliases[$abstract]) ? $this->aliases[$abstract] : $abstract;
  336. }
  337. public function getBindings()
  338. {
  339. return $this->bindings;
  340. }
  341. protected function dropStaleInstances($abstract)
  342. {
  343. unset($this->instances[$abstract]);
  344. unset($this->aliases[$abstract]);
  345. }
  346. public function forgetInstance($abstract)
  347. {
  348. unset($this->instances[$abstract]);
  349. }
  350. public function forgetInstances()
  351. {
  352. $this->instances = array();
  353. }
  354. public function offsetExists($key)
  355. {
  356. return isset($this->bindings[$key]);
  357. }
  358. public function offsetGet($key)
  359. {
  360. return $this->make($key);
  361. }
  362. public function offsetSet($key, $value)
  363. {
  364. if (!$value instanceof Closure) {
  365. $value = function () use($value) {
  366. return $value;
  367. };
  368. }
  369. $this->bind($key, $value);
  370. }
  371. public function offsetUnset($key)
  372. {
  373. unset($this->bindings[$key]);
  374. unset($this->instances[$key]);
  375. }
  376. }
  377. namespace Symfony\Component\HttpKernel;
  378. use Symfony\Component\HttpFoundation\Request;
  379. use Symfony\Component\HttpFoundation\Response;
  380. interface HttpKernelInterface
  381. {
  382. const MASTER_REQUEST = 1;
  383. const SUB_REQUEST = 2;
  384. public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
  385. }
  386. namespace Symfony\Component\HttpKernel;
  387. use Symfony\Component\HttpFoundation\Request;
  388. use Symfony\Component\HttpFoundation\Response;
  389. interface TerminableInterface
  390. {
  391. public function terminate(Request $request, Response $response);
  392. }
  393. namespace Illuminate\Support\Contracts;
  394. interface ResponsePreparerInterface
  395. {
  396. public function prepareResponse($value);
  397. public function readyForResponses();
  398. }
  399. namespace Illuminate\Foundation;
  400. use Closure;
  401. use Illuminate\Http\Request;
  402. use Illuminate\Http\Response;
  403. use Illuminate\Config\FileLoader;
  404. use Illuminate\Container\Container;
  405. use Illuminate\Filesystem\Filesystem;
  406. use Illuminate\Support\Facades\Facade;
  407. use Illuminate\Events\EventServiceProvider;
  408. use Illuminate\Routing\RoutingServiceProvider;
  409. use Illuminate\Exception\ExceptionServiceProvider;
  410. use Illuminate\Config\FileEnvironmentVariablesLoader;
  411. use Symfony\Component\HttpKernel\HttpKernelInterface;
  412. use Symfony\Component\HttpKernel\TerminableInterface;
  413. use Symfony\Component\HttpKernel\Exception\HttpException;
  414. use Symfony\Component\Debug\Exception\FatalErrorException;
  415. use Illuminate\Support\Contracts\ResponsePreparerInterface;
  416. use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
  417. use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
  418. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  419. class Application extends Container implements HttpKernelInterface, TerminableInterface, ResponsePreparerInterface
  420. {
  421. const VERSION = '4.2.4';
  422. protected $booted = false;
  423. protected $bootingCallbacks = array();
  424. protected $bootedCallbacks = array();
  425. protected $finishCallbacks = array();
  426. protected $shutdownCallbacks = array();
  427. protected $middlewares = array();
  428. protected $serviceProviders = array();
  429. protected $loadedProviders = array();
  430. protected $deferredServices = array();
  431. protected static $requestClass = 'Illuminate\\Http\\Request';
  432. public function __construct(Request $request = null)
  433. {
  434. $this->registerBaseBindings($request ?: $this->createNewRequest());
  435. $this->registerBaseServiceProviders();
  436. $this->registerBaseMiddlewares();
  437. }
  438. protected function createNewRequest()
  439. {
  440. return forward_static_call(array(static::$requestClass, 'createFromGlobals'));
  441. }
  442. protected function registerBaseBindings($request)
  443. {
  444. $this->instance('request', $request);
  445. $this->instance('Illuminate\\Container\\Container', $this);
  446. }
  447. protected function registerBaseServiceProviders()
  448. {
  449. foreach (array('Event', 'Exception', 'Routing') as $name) {
  450. $this->{"register{$name}Provider"}();
  451. }
  452. }
  453. protected function registerExceptionProvider()
  454. {
  455. $this->register(new ExceptionServiceProvider($this));
  456. }
  457. protected function registerRoutingProvider()
  458. {
  459. $this->register(new RoutingServiceProvider($this));
  460. }
  461. protected function registerEventProvider()
  462. {
  463. $this->register(new EventServiceProvider($this));
  464. }
  465. public function bindInstallPaths(array $paths)
  466. {
  467. $this->instance('path', realpath($paths['app']));
  468. foreach (array_except($paths, array('app')) as $key => $value) {
  469. $this->instance("path.{$key}", realpath($value));
  470. }
  471. }
  472. public static function getBootstrapFile()
  473. {
  474. return 'C:\\xampp\\htdocs\\laravel\\vendor\\laravel\\framework\\src\\Illuminate\\Foundation' . '/start.php';
  475. }
  476. public function startExceptionHandling()
  477. {
  478. $this['exception']->register($this->environment());
  479. $this['exception']->setDebug($this['config']['app.debug']);
  480. }
  481. public function environment()
  482. {
  483. if (count(func_get_args()) > 0) {
  484. return in_array($this['env'], func_get_args());
  485. } else {
  486. return $this['env'];
  487. }
  488. }
  489. public function isLocal()
  490. {
  491. return $this['env'] == 'local';
  492. }
  493. public function detectEnvironment($envs)
  494. {
  495. $args = isset($_SERVER['argv']) ? $_SERVER['argv'] : null;
  496. return $this['env'] = with(new EnvironmentDetector())->detect($envs, $args);
  497. }
  498. public function runningInConsole()
  499. {
  500. return php_sapi_name() == 'cli';
  501. }
  502. public function runningUnitTests()
  503. {
  504. return $this['env'] == 'testing';
  505. }
  506. public function forceRegister($provider, $options = array())
  507. {
  508. return $this->register($provider, $options, true);
  509. }
  510. public function register($provider, $options = array(), $force = false)
  511. {
  512. if ($registered = $this->getRegistered($provider) && !$force) {
  513. return $registered;
  514. }
  515. if (is_string($provider)) {
  516. $provider = $this->resolveProviderClass($provider);
  517. }
  518. $provider->register();
  519. foreach ($options as $key => $value) {
  520. $this[$key] = $value;
  521. }
  522. $this->markAsRegistered($provider);
  523. if ($this->booted) {
  524. $provider->boot();
  525. }
  526. return $provider;
  527. }
  528. public function getRegistered($provider)
  529. {
  530. $name = is_string($provider) ? $provider : get_class($provider);
  531. if (array_key_exists($name, $this->loadedProviders)) {
  532. return array_first($this->serviceProviders, function ($key, $value) use($name) {
  533. return get_class($value) == $name;
  534. });
  535. }
  536. }
  537. public function resolveProviderClass($provider)
  538. {
  539. return new $provider($this);
  540. }
  541. protected function markAsRegistered($provider)
  542. {
  543. $this['events']->fire($class = get_class($provider), array($provider));
  544. $this->serviceProviders[] = $provider;
  545. $this->loadedProviders[$class] = true;
  546. }
  547. public function loadDeferredProviders()
  548. {
  549. foreach ($this->deferredServices as $service => $provider) {
  550. $this->loadDeferredProvider($service);
  551. }
  552. $this->deferredServices = array();
  553. }
  554. protected function loadDeferredProvider($service)
  555. {
  556. $provider = $this->deferredServices[$service];
  557. if (!isset($this->loadedProviders[$provider])) {
  558. $this->registerDeferredProvider($provider, $service);
  559. }
  560. }
  561. public function registerDeferredProvider($provider, $service = null)
  562. {
  563. if ($service) {
  564. unset($this->deferredServices[$service]);
  565. }
  566. $this->register($instance = new $provider($this));
  567. if (!$this->booted) {
  568. $this->booting(function () use($instance) {
  569. $instance->boot();
  570. });
  571. }
  572. }
  573. public function make($abstract, $parameters = array())
  574. {
  575. $abstract = $this->getAlias($abstract);
  576. if (isset($this->deferredServices[$abstract])) {
  577. $this->loadDeferredProvider($abstract);
  578. }
  579. return parent::make($abstract, $parameters);
  580. }
  581. public function before($callback)
  582. {
  583. return $this['router']->before($callback);
  584. }
  585. public function after($callback)
  586. {
  587. return $this['router']->after($callback);
  588. }
  589. public function finish($callback)
  590. {
  591. $this->finishCallbacks[] = $callback;
  592. }
  593. public function shutdown($callback = null)
  594. {
  595. if (is_null($callback)) {
  596. $this->fireAppCallbacks($this->shutdownCallbacks);
  597. } else {
  598. $this->shutdownCallbacks[] = $callback;
  599. }
  600. }
  601. public function useArraySessions(Closure $callback)
  602. {
  603. $this->bind('session.reject', function () use($callback) {
  604. return $callback;
  605. });
  606. }
  607. public function isBooted()
  608. {
  609. return $this->booted;
  610. }
  611. public function boot()
  612. {
  613. if ($this->booted) {
  614. return;
  615. }
  616. array_walk($this->serviceProviders, function ($p) {
  617. $p->boot();
  618. });
  619. $this->bootApplication();
  620. }
  621. protected function bootApplication()
  622. {
  623. $this->fireAppCallbacks($this->bootingCallbacks);
  624. $this->booted = true;
  625. $this->fireAppCallbacks($this->bootedCallbacks);
  626. }
  627. public function booting($callback)
  628. {
  629. $this->bootingCallbacks[] = $callback;
  630. }
  631. public function booted($callback)
  632. {
  633. $this->bootedCallbacks[] = $callback;
  634. if ($this->isBooted()) {
  635. $this->fireAppCallbacks(array($callback));
  636. }
  637. }
  638. public function run(SymfonyRequest $request = null)
  639. {
  640. $request = $request ?: $this['request'];
  641. $response = with($stack = $this->getStackedClient())->handle($request);
  642. $response->send();
  643. $stack->terminate($request, $response);
  644. }
  645. protected function getStackedClient()
  646. {
  647. $sessionReject = $this->bound('session.reject') ? $this['session.reject'] : null;
  648. $client = with(new \Stack\Builder())->push('Illuminate\\Cookie\\Guard', $this['encrypter'])->push('Illuminate\\Cookie\\Queue', $this['cookie'])->push('Illuminate\\Session\\Middleware', $this['session'], $sessionReject);
  649. $this->mergeCustomMiddlewares($client);
  650. return $client->resolve($this);
  651. }
  652. protected function mergeCustomMiddlewares(\Stack\Builder $stack)
  653. {
  654. foreach ($this->middlewares as $middleware) {
  655. list($class, $parameters) = array_values($middleware);
  656. array_unshift($parameters, $class);
  657. call_user_func_array(array($stack, 'push'), $parameters);
  658. }
  659. }
  660. protected function registerBaseMiddlewares()
  661. {
  662. }
  663. public function middleware($class, array $parameters = array())
  664. {
  665. $this->middlewares[] = compact('class', 'parameters');
  666. return $this;
  667. }
  668. public function forgetMiddleware($class)
  669. {
  670. $this->middlewares = array_filter($this->middlewares, function ($m) use($class) {
  671. return $m['class'] != $class;
  672. });
  673. }
  674. public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  675. {
  676. try {
  677. $this->refreshRequest($request = Request::createFromBase($request));
  678. $this->boot();
  679. return $this->dispatch($request);
  680. } catch (\Exception $e) {
  681. if ($this->runningUnitTests()) {
  682. throw $e;
  683. }
  684. return $this['exception']->handleException($e);
  685. }
  686. }
  687. public function dispatch(Request $request)
  688. {
  689. if ($this->isDownForMaintenance()) {
  690. $response = $this['events']->until('illuminate.app.down');
  691. if (!is_null($response)) {
  692. return $this->prepareResponse($response, $request);
  693. }
  694. }
  695. if ($this->runningUnitTests() && !$this['session']->isStarted()) {
  696. $this['session']->start();
  697. }
  698. return $this['router']->dispatch($this->prepareRequest($request));
  699. }
  700. public function terminate(SymfonyRequest $request, SymfonyResponse $response)
  701. {
  702. $this->callFinishCallbacks($request, $response);
  703. $this->shutdown();
  704. }
  705. protected function refreshRequest(Request $request)
  706. {
  707. $this->instance('request', $request);
  708. Facade::clearResolvedInstance('request');
  709. }
  710. public function callFinishCallbacks(SymfonyRequest $request, SymfonyResponse $response)
  711. {
  712. foreach ($this->finishCallbacks as $callback) {
  713. call_user_func($callback, $request, $response);
  714. }
  715. }
  716. protected function fireAppCallbacks(array $callbacks)
  717. {
  718. foreach ($callbacks as $callback) {
  719. call_user_func($callback, $this);
  720. }
  721. }
  722. public function prepareRequest(Request $request)
  723. {
  724. if (!is_null($this['config']['session.driver']) && !$request->hasSession()) {
  725. $request->setSession($this['session']->driver());
  726. }
  727. return $request;
  728. }
  729. public function prepareResponse($value)
  730. {
  731. if (!$value instanceof SymfonyResponse) {
  732. $value = new Response($value);
  733. }
  734. return $value->prepare($this['request']);
  735. }
  736. public function readyForResponses()
  737. {
  738. return $this->booted;
  739. }
  740. public function isDownForMaintenance()
  741. {
  742. return file_exists($this['config']['app.manifest'] . '/down');
  743. }
  744. public function down(Closure $callback)
  745. {
  746. $this['events']->listen('illuminate.app.down', $callback);
  747. }
  748. public function abort($code, $message = '', array $headers = array())
  749. {
  750. if ($code == 404) {
  751. throw new NotFoundHttpException($message);
  752. } else {
  753. throw new HttpException($code, $message, null, $headers);
  754. }
  755. }
  756. public function missing(Closure $callback)
  757. {
  758. $this->error(function (NotFoundHttpException $e) use($callback) {
  759. return call_user_func($callback, $e);
  760. });
  761. }
  762. public function error(Closure $callback)
  763. {
  764. $this['exception']->error($callback);
  765. }
  766. public function pushError(Closure $callback)
  767. {
  768. $this['exception']->pushError($callback);
  769. }
  770. public function fatal(Closure $callback)
  771. {
  772. $this->error(function (FatalErrorException $e) use($callback) {
  773. return call_user_func($callback, $e);
  774. });
  775. }
  776. public function getConfigLoader()
  777. {
  778. return new FileLoader(new Filesystem(), $this['path'] . '/config');
  779. }
  780. public function getEnvironmentVariablesLoader()
  781. {
  782. return new FileEnvironmentVariablesLoader(new Filesystem(), $this['path.base']);
  783. }
  784. public function getProviderRepository()
  785. {
  786. $manifest = $this['config']['app.manifest'];
  787. return new ProviderRepository(new Filesystem(), $manifest);
  788. }
  789. public function getLoadedProviders()
  790. {
  791. return $this->loadedProviders;
  792. }
  793. public function setDeferredServices(array $services)
  794. {
  795. $this->deferredServices = $services;
  796. }
  797. public function isDeferredService($service)
  798. {
  799. return isset($this->deferredServices[$service]);
  800. }
  801. public static function requestClass($class = null)
  802. {
  803. if (!is_null($class)) {
  804. static::$requestClass = $class;
  805. }
  806. return static::$requestClass;
  807. }
  808. public function setRequestForConsoleEnvironment()
  809. {
  810. $url = $this['config']->get('app.url', 'http://localhost');
  811. $parameters = array($url, 'GET', array(), array(), array(), $_SERVER);
  812. $this->refreshRequest(static::onRequest('create', $parameters));
  813. }
  814. public static function onRequest($method, $parameters = array())
  815. {
  816. return forward_static_call_array(array(static::requestClass(), $method), $parameters);
  817. }
  818. public function getLocale()
  819. {
  820. return $this['config']->get('app.locale');
  821. }
  822. public function setLocale($locale)
  823. {
  824. $this['config']->set('app.locale', $locale);
  825. $this['translator']->setLocale($locale);
  826. $this['events']->fire('locale.changed', array($locale));
  827. }
  828. public function registerCoreContainerAliases()
  829. {
  830. $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');
  831. foreach ($aliases as $key => $alias) {
  832. $this->alias($key, $alias);
  833. }
  834. }
  835. public function __get($key)
  836. {
  837. return $this[$key];
  838. }
  839. public function __set($key, $value)
  840. {
  841. $this[$key] = $value;
  842. }
  843. }
  844. namespace Illuminate\Foundation;
  845. use Closure;
  846. class EnvironmentDetector
  847. {
  848. public function detect($environments, $consoleArgs = null)
  849. {
  850. if ($consoleArgs) {
  851. return $this->detectConsoleEnvironment($environments, $consoleArgs);
  852. } else {
  853. return $this->detectWebEnvironment($environments);
  854. }
  855. }
  856. protected function detectWebEnvironment($environments)
  857. {
  858. if ($environments instanceof Closure) {
  859. return call_user_func($environments);
  860. }
  861. foreach ($environments as $environment => $hosts) {
  862. foreach ((array) $hosts as $host) {
  863. if ($this->isMachine($host)) {
  864. return $environment;
  865. }
  866. }
  867. }
  868. return 'production';
  869. }
  870. protected function detectConsoleEnvironment($environments, array $args)
  871. {
  872. if (!is_null($value = $this->getEnvironmentArgument($args))) {
  873. return head(array_slice(explode('=', $value), 1));
  874. } else {
  875. return $this->detectWebEnvironment($environments);
  876. }
  877. }
  878. protected function getEnvironmentArgument(array $args)
  879. {
  880. return array_first($args, function ($k, $v) {
  881. return starts_with($v, '--env');
  882. });
  883. }
  884. public function isMachine($name)
  885. {
  886. return str_is($name, gethostname());
  887. }
  888. }
  889. namespace Illuminate\Http;
  890. use Symfony\Component\HttpFoundation\ParameterBag;
  891. use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
  892. class Request extends SymfonyRequest
  893. {
  894. protected $json;
  895. protected $sessionStore;
  896. public function instance()
  897. {
  898. return $this;
  899. }
  900. public function method()
  901. {
  902. return $this->getMethod();
  903. }
  904. public function root()
  905. {
  906. return rtrim($this->getSchemeAndHttpHost() . $this->getBaseUrl(), '/');
  907. }
  908. public function url()
  909. {
  910. return rtrim(preg_replace('/\\?.*/', '', $this->getUri()), '/');
  911. }
  912. public function fullUrl()
  913. {
  914. $query = $this->getQueryString();
  915. return $query ? $this->url() . '?' . $query : $this->url();
  916. }
  917. public function path()
  918. {
  919. $pattern = trim($this->getPathInfo(), '/');
  920. return $pattern == '' ? '/' : $pattern;
  921. }
  922. public function decodedPath()
  923. {
  924. return rawurldecode($this->path());
  925. }
  926. public function segment($index, $default = null)
  927. {
  928. return array_get($this->segments(), $index - 1, $default);
  929. }
  930. public function segments()
  931. {
  932. $segments = explode('/', $this->path());
  933. return array_values(array_filter($segments, function ($v) {
  934. return $v != '';
  935. }));
  936. }
  937. public function is()
  938. {
  939. foreach (func_get_args() as $pattern) {
  940. if (str_is($pattern, urldecode($this->path()))) {
  941. return true;
  942. }
  943. }
  944. return false;
  945. }
  946. public function ajax()
  947. {
  948. return $this->isXmlHttpRequest();
  949. }
  950. public function secure()
  951. {
  952. return $this->isSecure();
  953. }
  954. public function exists($key)
  955. {
  956. $keys = is_array($key) ? $key : func_get_args();
  957. $input = $this->all();
  958. foreach ($keys as $value) {
  959. if (!array_key_exists($value, $input)) {
  960. return false;
  961. }
  962. }
  963. return true;
  964. }
  965. public function has($key)
  966. {
  967. $keys = is_array($key) ? $key : func_get_args();
  968. foreach ($keys as $value) {
  969. if ($this->isEmptyString($value)) {
  970. return false;
  971. }
  972. }
  973. return true;
  974. }
  975. protected function isEmptyString($key)
  976. {
  977. $boolOrArray = is_bool($this->input($key)) || is_array($this->input($key));
  978. return !$boolOrArray && trim((string) $this->input($key)) === '';
  979. }
  980. public function all()
  981. {
  982. return array_merge_recursive($this->input(), $this->files->all());
  983. }
  984. public function input($key = null, $default = null)
  985. {
  986. $input = $this->getInputSource()->all() + $this->query->all();
  987. return array_get($input, $key, $default);
  988. }
  989. public function only($keys)
  990. {
  991. $keys = is_array($keys) ? $keys : func_get_args();
  992. return array_only($this->input(), $keys) + array_fill_keys($keys, null);
  993. }
  994. public function except($keys)
  995. {
  996. $keys = is_array($keys) ? $keys : func_get_args();
  997. $results = $this->input();
  998. foreach ($keys as $key) {
  999. array_forget($results, $key);
  1000. }
  1001. return $results;
  1002. }
  1003. public function query($key = null, $default = null)
  1004. {
  1005. return $this->retrieveItem('query', $key, $default);
  1006. }
  1007. public function hasCookie($key)
  1008. {
  1009. return !is_null($this->cookie($key));
  1010. }
  1011. public function cookie($key = null, $default = null)
  1012. {
  1013. return $this->retrieveItem('cookies', $key, $default);
  1014. }
  1015. public function file($key = null, $default = null)
  1016. {
  1017. return array_get($this->files->all(), $key, $default);
  1018. }
  1019. public function hasFile($key)
  1020. {
  1021. if (is_array($file = $this->file($key))) {
  1022. $file = head($file);
  1023. }
  1024. return $file instanceof \SplFileInfo && $file->getPath() != '';
  1025. }
  1026. public function header($key = null, $default = null)
  1027. {
  1028. return $this->retrieveItem('headers', $key, $default);
  1029. }
  1030. public function server($key = null, $default = null)
  1031. {
  1032. return $this->retrieveItem('server', $key, $default);
  1033. }
  1034. public function old($key = null, $default = null)
  1035. {
  1036. return $this->session()->getOldInput($key, $default);
  1037. }
  1038. public function flash($filter = null, $keys = array())
  1039. {
  1040. $flash = !is_null($filter) ? $this->{$filter}($keys) : $this->input();
  1041. $this->session()->flashInput($flash);
  1042. }
  1043. public function flashOnly($keys)
  1044. {
  1045. $keys = is_array($keys) ? $keys : func_get_args();
  1046. return $this->flash('only', $keys);
  1047. }
  1048. public function flashExcept($keys)
  1049. {
  1050. $keys = is_array($keys) ? $keys : func_get_args();
  1051. return $this->flash('except', $keys);
  1052. }
  1053. public function flush()
  1054. {
  1055. $this->session()->flashInput(array());
  1056. }
  1057. protected function retrieveItem($source, $key, $default)
  1058. {
  1059. if (is_null($key)) {
  1060. return $this->{$source}->all();
  1061. } else {
  1062. return $this->{$source}->get($key, $default, true);
  1063. }
  1064. }
  1065. public function merge(array $input)
  1066. {
  1067. $this->getInputSource()->add($input);
  1068. }
  1069. public function replace(array $input)
  1070. {
  1071. $this->getInputSource()->replace($input);
  1072. }
  1073. public function json($key = null, $default = null)
  1074. {
  1075. if (!isset($this->json)) {
  1076. $this->json = new ParameterBag((array) json_decode($this->getContent(), true));
  1077. }
  1078. if (is_null($key)) {
  1079. return $this->json;
  1080. }
  1081. return array_get($this->json->all(), $key, $default);
  1082. }
  1083. protected function getInputSource()
  1084. {
  1085. if ($this->isJson()) {
  1086. return $this->json();
  1087. }
  1088. return $this->getMethod() == 'GET' ? $this->query : $this->request;
  1089. }
  1090. public function isJson()
  1091. {
  1092. return str_contains($this->header('CONTENT_TYPE'), '/json');
  1093. }
  1094. public function wantsJson()
  1095. {
  1096. $acceptable = $this->getAcceptableContentTypes();
  1097. return isset($acceptable[0]) && $acceptable[0] == 'application/json';
  1098. }
  1099. public function format($default = 'html')
  1100. {
  1101. foreach ($this->getAcceptableContentTypes() as $type) {
  1102. if ($format = $this->getFormat($type)) {
  1103. return $format;
  1104. }
  1105. }
  1106. return $default;
  1107. }
  1108. public static function createFromBase(SymfonyRequest $request)
  1109. {
  1110. if ($request instanceof static) {
  1111. return $request;
  1112. }
  1113. return with(new static())->duplicate($request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all());
  1114. }
  1115. public function session()
  1116. {
  1117. if (!$this->hasSession()) {
  1118. throw new \RuntimeException('Session store not set on request.');
  1119. }
  1120. return $this->getSession();
  1121. }
  1122. }
  1123. namespace Illuminate\Http;
  1124. use Symfony\Component\HttpKernel\HttpKernelInterface;
  1125. use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
  1126. class FrameGuard implements HttpKernelInterface
  1127. {
  1128. protected $app;
  1129. public function __construct(HttpKernelInterface $app)
  1130. {
  1131. $this->app = $app;
  1132. }
  1133. public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  1134. {
  1135. $response = $this->app->handle($request, $type, $catch);
  1136. $response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
  1137. return $response;
  1138. }
  1139. }
  1140. namespace Symfony\Component\HttpFoundation;
  1141. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  1142. class Request
  1143. {
  1144. const HEADER_CLIENT_IP = 'client_ip';
  1145. const HEADER_CLIENT_HOST = 'client_host';
  1146. const HEADER_CLIENT_PROTO = 'client_proto';
  1147. const HEADER_CLIENT_PORT = 'client_port';
  1148. protected static $trustedProxies = array();
  1149. protected static $trustedHostPatterns = array();
  1150. protected static $trustedHosts = array();
  1151. protected static $trustedHeaders = array(self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT');
  1152. protected static $httpMethodParameterOverride = false;
  1153. public $attributes;
  1154. public $request;
  1155. public $query;
  1156. public $server;
  1157. public $files;
  1158. public $cookies;
  1159. public $headers;
  1160. protected $content;
  1161. protected $languages;
  1162. protected $charsets;
  1163. protected $encodings;
  1164. protected $acceptableContentTypes;
  1165. protected $pathInfo;
  1166. protected $requestUri;
  1167. protected $baseUrl;
  1168. protected $basePath;
  1169. protected $method;
  1170. protected $format;
  1171. protected $session;
  1172. protected $locale;
  1173. protected $defaultLocale = 'en';
  1174. protected static $formats;
  1175. protected static $requestFactory;
  1176. public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1177. {
  1178. $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
  1179. }
  1180. public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1181. {
  1182. $this->request = new ParameterBag($request);
  1183. $this->query = new ParameterBag($query);
  1184. $this->attributes = new ParameterBag($attributes);
  1185. $this->cookies = new ParameterBag($cookies);
  1186. $this->files = new FileBag($files);
  1187. $this->server = new ServerBag($server);
  1188. $this->headers = new HeaderBag($this->server->getHeaders());
  1189. $this->content = $content;
  1190. $this->languages = null;
  1191. $this->charsets = null;
  1192. $this->encodings = null;
  1193. $this->acceptableContentTypes = null;
  1194. $this->pathInfo = null;
  1195. $this->requestUri = null;
  1196. $this->baseUrl = null;
  1197. $this->basePath = null;
  1198. $this->method = null;
  1199. $this->format = null;
  1200. }
  1201. public static function createFromGlobals()
  1202. {
  1203. $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER);
  1204. if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH'))) {
  1205. parse_str($request->getContent(), $data);
  1206. $request->request = new ParameterBag($data);
  1207. }
  1208. return $request;
  1209. }
  1210. public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null)
  1211. {
  1212. $server = array_replace(array('SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony/2.X', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time()), $server);
  1213. $server['PATH_INFO'] = '';
  1214. $server['REQUEST_METHOD'] = strtoupper($method);
  1215. $components = parse_url($uri);
  1216. if (isset($components['host'])) {
  1217. $server['SERVER_NAME'] = $components['host'];
  1218. $server['HTTP_HOST'] = $components['host'];
  1219. }
  1220. if (isset($components['scheme'])) {
  1221. if ('https' === $components['scheme']) {
  1222. $server['HTTPS'] = 'on';
  1223. $server['SERVER_PORT'] = 443;
  1224. } else {
  1225. unset($server['HTTPS']);
  1226. $server['SERVER_PORT'] = 80;
  1227. }
  1228. }
  1229. if (isset($components['port'])) {
  1230. $server['SERVER_PORT'] = $components['port'];
  1231. $server['HTTP_HOST'] = $server['HTTP_HOST'] . ':' . $components['port'];
  1232. }
  1233. if (isset($components['user'])) {
  1234. $server['PHP_AUTH_USER'] = $components['user'];
  1235. }
  1236. if (isset($components['pass'])) {
  1237. $server['PHP_AUTH_PW'] = $components['pass'];
  1238. }
  1239. if (!isset($components['path'])) {
  1240. $components['path'] = '/';
  1241. }
  1242. switch (strtoupper($method)) {
  1243. case 'POST':
  1244. case 'PUT':
  1245. case 'DELETE':
  1246. if (!isset($server['CONTENT_TYPE'])) {
  1247. $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
  1248. }
  1249. case 'PATCH':
  1250. $request = $parameters;
  1251. $query = array();
  1252. break;
  1253. default:
  1254. $request = array();
  1255. $query = $parameters;
  1256. break;
  1257. }
  1258. $queryString = '';
  1259. if (isset($components['query'])) {
  1260. parse_str(html_entity_decode($components['query']), $qs);
  1261. if ($query) {
  1262. $query = array_replace($qs, $query);
  1263. $queryString = http_build_query($query, '', '&');
  1264. } else {
  1265. $query = $qs;
  1266. $queryString = $components['query'];
  1267. }
  1268. } elseif ($query) {
  1269. $queryString = http_build_query($query, '', '&');
  1270. }
  1271. $server['REQUEST_URI'] = $components['path'] . ('' !== $queryString ? '?' . $queryString : '');
  1272. $server['QUERY_STRING'] = $queryString;
  1273. return self::createRequestFromFactory($query, $request, array(), $cookies, $files, $server, $content);
  1274. }
  1275. public static function setFactory($callable)
  1276. {
  1277. self::$requestFactory = $callable;
  1278. }
  1279. public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null)
  1280. {
  1281. $dup = clone $this;
  1282. if ($query !== null) {
  1283. $dup->query = new ParameterBag($query);
  1284. }
  1285. if ($request !== null) {
  1286. $dup->request = new ParameterBag($request);
  1287. }
  1288. if ($attributes !== null) {
  1289. $dup->attributes = new ParameterBag($attributes);
  1290. }
  1291. if ($cookies !== null) {
  1292. $dup->cookies = new ParameterBag($cookies);
  1293. }
  1294. if ($files !== null) {
  1295. $dup->files = new FileBag($files);
  1296. }
  1297. if ($server !== null) {
  1298. $dup->server = new ServerBag($server);
  1299. $dup->headers = new HeaderBag($dup->server->getHeaders());
  1300. }
  1301. $dup->languages = null;
  1302. $dup->charsets = null;
  1303. $dup->encodings = null;
  1304. $dup->acceptableContentTypes = null;
  1305. $dup->pathInfo = null;
  1306. $dup->requestUri = null;
  1307. $dup->baseUrl = null;
  1308. $dup->basePath = null;
  1309. $dup->method = null;
  1310. $dup->format = null;
  1311. if (!$dup->get('_format') && $this->get('_format')) {
  1312. $dup->attributes->set('_format', $this->get('_format'));
  1313. }
  1314. if (!$dup->getRequestFormat(null)) {
  1315. $dup->setRequestFormat($format = $this->getRequestFormat(null));
  1316. }
  1317. return $dup;
  1318. }
  1319. public function __clone()
  1320. {
  1321. $this->query = clone $this->query;
  1322. $this->request = clone $this->request;
  1323. $this->attributes = clone $this->attributes;
  1324. $this->cookies = clone $this->cookies;
  1325. $this->files = clone $this->files;
  1326. $this->server = clone $this->server;
  1327. $this->headers = clone $this->headers;
  1328. }
  1329. public function __toString()
  1330. {
  1331. return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL')) . '
  1332. ' . $this->headers . '
  1333. ' . $this->getContent();
  1334. }
  1335. public function overrideGlobals()
  1336. {
  1337. $_GET = $this->query->all();
  1338. $_POST = $this->request->all();
  1339. $_SERVER = $this->server->all();
  1340. $_COOKIE = $this->cookies->all();
  1341. foreach ($this->headers->all() as $key => $value) {
  1342. $key = strtoupper(str_replace('-', '_', $key));
  1343. if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
  1344. $_SERVER[$key] = implode(', ', $value);
  1345. } else {
  1346. $_SERVER['HTTP_' . $key] = implode(', ', $value);
  1347. }
  1348. }
  1349. $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE);
  1350. $requestOrder = ini_get('request_order') ?: ini_get('variables_order');
  1351. $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp';
  1352. $_REQUEST = array();
  1353. foreach (str_split($requestOrder) as $order) {
  1354. $_REQUEST = array_merge($_REQUEST, $request[$order]);
  1355. }
  1356. }
  1357. public static function setTrustedProxies(array $proxies)
  1358. {
  1359. self::$trustedProxies = $proxies;
  1360. }
  1361. public static function getTrustedProxies()
  1362. {
  1363. return self::$trustedProxies;
  1364. }
  1365. public static function setTrustedHosts(array $hostPatterns)
  1366. {
  1367. self::$trustedHostPatterns = array_map(function ($hostPattern) {
  1368. return sprintf('{%s}i', str_replace('}', '\\}', $hostPattern));
  1369. }, $hostPatterns);
  1370. self::$trustedHosts = array();
  1371. }
  1372. public static function getTrustedHosts()
  1373. {
  1374. return self::$trustedHostPatterns;
  1375. }
  1376. public static function setTrustedHeaderName($key, $value)
  1377. {
  1378. if (!array_key_exists($key, self::$trustedHeaders)) {
  1379. throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key));
  1380. }
  1381. self::$trustedHeaders[$key] = $value;
  1382. }
  1383. public static function getTrustedHeaderName($key)
  1384. {
  1385. if (!array_key_exists($key, self::$trustedHeaders)) {
  1386. throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key));
  1387. }
  1388. return self::$trustedHeaders[$key];
  1389. }
  1390. public static function normalizeQueryString($qs)
  1391. {
  1392. if ('' == $qs) {
  1393. return '';
  1394. }
  1395. $parts = array();
  1396. $order = array();
  1397. foreach (explode('&', $qs) as $param) {
  1398. if ('' === $param || '=' === $param[0]) {
  1399. continue;
  1400. }
  1401. $keyValuePair = explode('=', $param, 2);
  1402. $parts[] = isset($keyValuePair[1]) ? rawurlencode(urldecode($keyValuePair[0])) . '=' . rawurlencode(urldecode($keyValuePair[1])) : rawurlencode(urldecode($keyValuePair[0]));
  1403. $order[] = urldecode($keyValuePair[0]);
  1404. }
  1405. array_multisort($order, SORT_ASC, $parts);
  1406. return implode('&', $parts);
  1407. }
  1408. public static function enableHttpMethodParameterOverride()
  1409. {
  1410. self::$httpMethodParameterOverride = true;
  1411. }
  1412. public static function getHttpMethodParameterOverride()
  1413. {
  1414. return self::$httpMethodParameterOverride;
  1415. }
  1416. public function get($key, $default = null, $deep = false)
  1417. {
  1418. return $this->query->get($key, $this->attributes->get($key, $this->request->get($key, $default, $deep), $deep), $deep);
  1419. }
  1420. public function getSession()
  1421. {
  1422. return $this->session;
  1423. }
  1424. public function hasPreviousSession()
  1425. {
  1426. return $this->hasSession() && $this->cookies->has($this->session->getName());
  1427. }
  1428. public function hasSession()
  1429. {
  1430. return null !== $this->session;
  1431. }
  1432. public function setSession(SessionInterface $session)
  1433. {
  1434. $this->session = $session;
  1435. }
  1436. public function getClientIps()
  1437. {
  1438. $ip = $this->server->get('REMOTE_ADDR');
  1439. if (!self::$trustedProxies) {
  1440. return array($ip);
  1441. }
  1442. if (!self::$trustedHeaders[self::HEADER_CLIENT_IP] || !$this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
  1443. return array($ip);
  1444. }
  1445. $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
  1446. $clientIps[] = $ip;
  1447. $ip = $clientIps[0];
  1448. foreach ($clientIps as $key => $clientIp) {
  1449. if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
  1450. unset($clientIps[$key]);
  1451. }
  1452. }
  1453. return $clientIps ? array_reverse($clientIps) : array($ip);
  1454. }
  1455. public function getClientIp()
  1456. {
  1457. $ipAddresses = $this->getClientIps();
  1458. return $ipAddresses[0];
  1459. }
  1460. public function getScriptName()
  1461. {
  1462. return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', ''));
  1463. }
  1464. public function getPathInfo()
  1465. {
  1466. if (null === $this->pathInfo) {
  1467. $this->pathInfo = $this->preparePathInfo();
  1468. }
  1469. return $this->pathInfo;
  1470. }
  1471. public function getBasePath()
  1472. {
  1473. if (null === $this->basePath) {
  1474. $this->basePath = $this->prepareBasePath();
  1475. }
  1476. return $this->basePath;
  1477. }
  1478. public function getBaseUrl()
  1479. {
  1480. if (null === $this->baseUrl) {
  1481. $this->baseUrl = $this->prepareBaseUrl();
  1482. }
  1483. return $this->baseUrl;
  1484. }
  1485. public function getScheme()
  1486. {
  1487. return $this->isSecure() ? 'https' : 'http';
  1488. }
  1489. public function getPort()
  1490. {
  1491. if (self::$trustedProxies) {
  1492. if (self::$trustedHeaders[self::HEADER_CLIENT_PORT] && ($port = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PORT]))) {
  1493. return $port;
  1494. }
  1495. if (self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && 'https' === $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO], 'http')) {
  1496. return 443;
  1497. }
  1498. }
  1499. if ($host = $this->headers->get('HOST')) {
  1500. if (false !== ($pos = strrpos($host, ':'))) {
  1501. return intval(substr($host, $pos + 1));
  1502. }
  1503. return 'https' === $this->getScheme() ? 443 : 80;
  1504. }
  1505. return $this->server->get('SERVER_PORT');
  1506. }
  1507. public function getUser()
  1508. {
  1509. return $this->server->get('PHP_AUTH_USER');
  1510. }
  1511. public function getPassword()
  1512. {
  1513. return $this->server->get('PHP_AUTH_PW');
  1514. }
  1515. public function getUserInfo()
  1516. {
  1517. $userinfo = $this->getUser();
  1518. $pass = $this->getPassword();
  1519. if ('' != $pass) {
  1520. $userinfo .= ":{$pass}";
  1521. }
  1522. return $userinfo;
  1523. }
  1524. public function getHttpHost()
  1525. {
  1526. $scheme = $this->getScheme();
  1527. $port = $this->getPort();
  1528. if ('http' == $scheme && $port == 80 || 'https' == $scheme && $port == 443) {
  1529. return $this->getHost();
  1530. }
  1531. return $this->getHost() . ':' . $port;
  1532. }
  1533. public function getRequestUri()
  1534. {
  1535. if (null === $this->requestUri) {
  1536. $this->requestUri = $this->prepareRequestUri();
  1537. }
  1538. return $this->requestUri;
  1539. }
  1540. public function getSchemeAndHttpHost()
  1541. {
  1542. return $this->getScheme() . '://' . $this->getHttpHost();
  1543. }
  1544. public function getUri()
  1545. {
  1546. if (null !== ($qs = $this->getQueryString())) {
  1547. $qs = '?' . $qs;
  1548. }
  1549. return $this->getSchemeAndHttpHost() . $this->getBaseUrl() . $this->getPathInfo() . $qs;
  1550. }
  1551. public function getUriForPath($path)
  1552. {
  1553. return $this->getSchemeAndHttpHost() . $this->getBaseUrl() . $path;
  1554. }
  1555. public function getQueryString()
  1556. {
  1557. $qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));
  1558. return '' === $qs ? null : $qs;
  1559. }
  1560. public function isSecure()
  1561. {
  1562. if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_PROTO] && ($proto = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_PROTO]))) {
  1563. return in_array(strtolower(current(explode(',', $proto))), array('https', 'on', 'ssl', '1'));
  1564. }
  1565. return 'on' == strtolower($this->server->get('HTTPS')) || 1 == $this->server->get('HTTPS');
  1566. }
  1567. public function getHost()
  1568. {
  1569. if (self::$trustedProxies && self::$trustedHeaders[self::HEADER_CLIENT_HOST] && ($host = $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_HOST]))) {
  1570. $elements = explode(',', $host);
  1571. $host = $elements[count($elements) - 1];
  1572. } elseif (!($host = $this->headers->get('HOST'))) {
  1573. if (!($host = $this->server->get('SERVER_NAME'))) {
  1574. $host = $this->server->get('SERVER_ADDR', '');
  1575. }
  1576. }
  1577. $host = strtolower(preg_replace('/:\\d+$/', '', trim($host)));
  1578. if ($host && !preg_match('/^\\[?(?:[a-zA-Z0-9-:\\]_]+\\.?)+$/', $host)) {
  1579. throw new \UnexpectedValueException(sprintf('Invalid Host "%s"', $host));
  1580. }
  1581. if (count(self::$trustedHostPatterns) > 0) {
  1582. if (in_array($host, self::$trustedHosts)) {
  1583. return $host;
  1584. }
  1585. foreach (self::$trustedHostPatterns as $pattern) {
  1586. if (preg_match($pattern, $host)) {
  1587. self::$trustedHosts[] = $host;
  1588. return $host;
  1589. }
  1590. }
  1591. throw new \UnexpectedValueException(sprintf('Untrusted Host "%s"', $host));
  1592. }
  1593. return $host;
  1594. }
  1595. public function setMethod($method)
  1596. {
  1597. $this->method = null;
  1598. $this->server->set('REQUEST_METHOD', $method);
  1599. }
  1600. public function getMethod()
  1601. {
  1602. if (null === $this->method) {
  1603. $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
  1604. if ('POST' === $this->method) {
  1605. if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) {
  1606. $this->method = strtoupper($method);
  1607. } elseif (self::$httpMethodParameterOverride) {
  1608. $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST')));
  1609. }
  1610. }
  1611. }
  1612. return $this->method;
  1613. }
  1614. public function getRealMethod()
  1615. {
  1616. return strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
  1617. }
  1618. public function getMimeType($format)
  1619. {
  1620. if (null === static::$formats) {
  1621. static::initializeFormats();
  1622. }
  1623. return isset(static::$formats[$format]) ? static::$formats[$format][0] : null;
  1624. }
  1625. public function getFormat($mimeType)
  1626. {
  1627. if (false !== ($pos = strpos($mimeType, ';'))) {
  1628. $mimeType = substr($mimeType, 0, $pos);
  1629. }
  1630. if (null === static::$formats) {
  1631. static::initializeFormats();
  1632. }
  1633. foreach (static::$formats as $format => $mimeTypes) {
  1634. if (in_array($mimeType, (array) $mimeTypes)) {
  1635. return $format;
  1636. }
  1637. }
  1638. }
  1639. public function setFormat($format, $mimeTypes)
  1640. {
  1641. if (null === static::$formats) {
  1642. static::initializeFormats();
  1643. }
  1644. static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes);
  1645. }
  1646. public function getRequestFormat($default = 'html')
  1647. {
  1648. if (null === $this->format) {
  1649. $this->format = $this->get('_format', $default);
  1650. }
  1651. return $this->format;
  1652. }
  1653. public function setRequestFormat($format)
  1654. {
  1655. $this->format = $format;
  1656. }
  1657. public function getContentType()
  1658. {
  1659. return $this->getFormat($this->headers->get('CONTENT_TYPE'));
  1660. }
  1661. public function setDefaultLocale($locale)
  1662. {
  1663. $this->defaultLocale = $locale;
  1664. if (null === $this->locale) {
  1665. $this->setPhpDefaultLocale($locale);
  1666. }
  1667. }
  1668. public function setLocale($locale)
  1669. {
  1670. $this->setPhpDefaultLocale($this->locale = $locale);
  1671. }
  1672. public function getLocale()
  1673. {
  1674. return null === $this->locale ? $this->defaultLocale : $this->locale;
  1675. }
  1676. public function isMethod($method)
  1677. {
  1678. return $this->getMethod() === strtoupper($method);
  1679. }
  1680. public function isMethodSafe()
  1681. {
  1682. return in_array($this->getMethod(), array('GET', 'HEAD'));
  1683. }
  1684. public function getContent($asResource = false)
  1685. {
  1686. if (false === $this->content || true === $asResource && null !== $this->content) {
  1687. throw new \LogicException('getContent() can only be called once when using the resource return type.');
  1688. }
  1689. if (true === $asResource) {
  1690. $this->content = false;
  1691. return fopen('php://input', 'rb');
  1692. }
  1693. if (null === $this->content) {
  1694. $this->content = file_get_contents('php://input');
  1695. }
  1696. return $this->content;
  1697. }
  1698. public function getETags()
  1699. {
  1700. return preg_split('/\\s*,\\s*/', $this->headers->get('if_none_match'), null, PREG_SPLIT_NO_EMPTY);
  1701. }
  1702. public function isNoCache()
  1703. {
  1704. return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma');
  1705. }
  1706. public function getPreferredLanguage(array $locales = null)
  1707. {
  1708. $preferredLanguages = $this->getLanguages();
  1709. if (empty($locales)) {
  1710. return isset($preferredLanguages[0]) ? $preferredLanguages[0] : null;
  1711. }
  1712. if (!$preferredLanguages) {
  1713. return $locales[0];
  1714. }
  1715. $extendedPreferredLanguages = array();
  1716. foreach ($preferredLanguages as $language) {
  1717. $extendedPreferredLanguages[] = $language;
  1718. if (false !== ($position = strpos($language, '_'))) {
  1719. $superLanguage = substr($language, 0, $position);
  1720. if (!in_array($superLanguage, $preferredLanguages)) {
  1721. $extendedPreferredLanguages[] = $superLanguage;
  1722. }
  1723. }
  1724. }
  1725. $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales));
  1726. return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0];
  1727. }
  1728. public function getLanguages()
  1729. {
  1730. if (null !== $this->languages) {
  1731. return $this->languages;
  1732. }
  1733. $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all();
  1734. $this->languages = array();
  1735. foreach (array_keys($languages) as $lang) {
  1736. if (strstr($lang, '-')) {
  1737. $codes = explode('-', $lang);
  1738. if ($codes[0] == 'i') {
  1739. if (count($codes) > 1) {
  1740. $lang = $codes[1];
  1741. }
  1742. } else {
  1743. for ($i = 0, $max = count($codes); $i < $max; $i++) {
  1744. if ($i == 0) {
  1745. $lang = strtolower($codes[0]);
  1746. } else {
  1747. $lang .= '_' . strtoupper($codes[$i]);
  1748. }
  1749. }
  1750. }
  1751. }
  1752. $this->languages[] = $lang;
  1753. }
  1754. return $this->languages;
  1755. }
  1756. public function getCharsets()
  1757. {
  1758. if (null !== $this->charsets) {
  1759. return $this->charsets;
  1760. }
  1761. return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all());
  1762. }
  1763. public function getEncodings()
  1764. {
  1765. if (null !== $this->encodings) {
  1766. return $this->encodings;
  1767. }
  1768. return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all());
  1769. }
  1770. public function getAcceptableContentTypes()
  1771. {
  1772. if (null !== $this->acceptableContentTypes) {
  1773. return $this->acceptableContentTypes;
  1774. }
  1775. return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all());
  1776. }
  1777. public function isXmlHttpRequest()
  1778. {
  1779. return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
  1780. }
  1781. protected function prepareRequestUri()
  1782. {
  1783. $requestUri = '';
  1784. if ($this->headers->has('X_ORIGINAL_URL')) {
  1785. $requestUri = $this->headers->get('X_ORIGINAL_URL');
  1786. $this->headers->remove('X_ORIGINAL_URL');
  1787. $this->server->remove('HTTP_X_ORIGINAL_URL');
  1788. $this->server->remove('UNENCODED_URL');
  1789. $this->server->remove('IIS_WasUrlRewritten');
  1790. } elseif ($this->headers->has('X_REWRITE_URL')) {
  1791. $requestUri = $this->headers->get('X_REWRITE_URL');
  1792. $this->headers->remove('X_REWRITE_URL');
  1793. } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') {
  1794. $requestUri = $this->server->get('UNENCODED_URL');
  1795. $this->server->remove('UNENCODED_URL');
  1796. $this->server->remove('IIS_WasUrlRewritten');
  1797. } elseif ($this->server->has('REQUEST_URI')) {
  1798. $requestUri = $this->server->get('REQUEST_URI');
  1799. $schemeAndHttpHost = $this->getSchemeAndHttpHost();
  1800. if (strpos($requestUri, $schemeAndHttpHost) === 0) {
  1801. $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
  1802. }
  1803. } elseif ($this->server->has('ORIG_PATH_INFO')) {
  1804. $requestUri = $this->server->get('ORIG_PATH_INFO');
  1805. if ('' != $this->server->get('QUERY_STRING')) {
  1806. $requestUri .= '?' . $this->server->get('QUERY_STRING');
  1807. }
  1808. $this->server->remove('ORIG_PATH_INFO');
  1809. }
  1810. $this->server->set('REQUEST_URI', $requestUri);
  1811. return $requestUri;
  1812. }
  1813. protected function prepareBaseUrl()
  1814. {
  1815. $filename = basename($this->server->get('SCRIPT_FILENAME'));
  1816. if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
  1817. $baseUrl = $this->server->get('SCRIPT_NAME');
  1818. } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
  1819. $baseUrl = $this->server->get('PHP_SELF');
  1820. } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
  1821. $baseUrl = $this->server->get('ORIG_SCRIPT_NAME');
  1822. } else {
  1823. $path = $this->server->get('PHP_SELF', '');
  1824. $file = $this->server->get('SCRIPT_FILENAME', '');
  1825. $segs = explode('/', trim($file, '/'));
  1826. $segs = array_reverse($segs);
  1827. $index = 0;
  1828. $last = count($segs);
  1829. $baseUrl = '';
  1830. do {
  1831. $seg = $segs[$index];
  1832. $baseUrl = '/' . $seg . $baseUrl;
  1833. ++$index;
  1834. } while ($last > $index && false !== ($pos = strpos($path, $baseUrl)) && 0 != $pos);
  1835. }
  1836. $requestUri = $this->getRequestUri();
  1837. if ($baseUrl && false !== ($prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl))) {
  1838. return $prefix;
  1839. }
  1840. if ($baseUrl && false !== ($prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl)))) {
  1841. return rtrim($prefix, '/');
  1842. }
  1843. $truncatedRequestUri = $requestUri;
  1844. if (false !== ($pos = strpos($requestUri, '?'))) {
  1845. $truncatedRequestUri = substr($requestUri, 0, $pos);
  1846. }
  1847. $basename = basename($baseUrl);
  1848. if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
  1849. return '';
  1850. }
  1851. if (strlen($requestUri) >= strlen($baseUrl) && false !== ($pos = strpos($requestUri, $baseUrl)) && $pos !== 0) {
  1852. $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
  1853. }
  1854. return rtrim($baseUrl, '/');
  1855. }
  1856. protected function prepareBasePath()
  1857. {
  1858. $filename = basename($this->server->get('SCRIPT_FILENAME'));
  1859. $baseUrl = $this->getBaseUrl();
  1860. if (empty($baseUrl)) {
  1861. return '';
  1862. }
  1863. if (basename($baseUrl) === $filename) {
  1864. $basePath = dirname($baseUrl);
  1865. } else {
  1866. $basePath = $baseUrl;
  1867. }
  1868. if ('\\' === DIRECTORY_SEPARATOR) {
  1869. $basePath = str_replace('\\', '/', $basePath);
  1870. }
  1871. return rtrim($basePath, '/');
  1872. }
  1873. protected function preparePathInfo()
  1874. {
  1875. $baseUrl = $this->getBaseUrl();
  1876. if (null === ($requestUri = $this->getRequestUri())) {
  1877. return '/';
  1878. }
  1879. $pathInfo = '/';
  1880. if ($pos = strpos($requestUri, '?')) {
  1881. $requestUri = substr($requestUri, 0, $pos);
  1882. }
  1883. if (null !== $baseUrl && false === ($pathInfo = substr($requestUri, strlen($baseUrl)))) {
  1884. return '/';
  1885. } elseif (null === $baseUrl) {
  1886. return $requestUri;
  1887. }
  1888. return (string) $pathInfo;
  1889. }
  1890. protected static function initializeFormats()
  1891. {
  1892. static::$formats = array('html' => array('text/html', 'application/xhtml+xml'), 'txt' => array('text/plain'), 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json' => array('application/json', 'application/x-json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), 'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), 'rss' => array('application/rss+xml'));
  1893. }
  1894. private function setPhpDefaultLocale($locale)
  1895. {
  1896. try {
  1897. if (class_exists('Locale', false)) {
  1898. \Locale::setDefault($locale);
  1899. }
  1900. } catch (\Exception $e) {
  1901. }
  1902. }
  1903. private function getUrlencodedPrefix($string, $prefix)
  1904. {
  1905. if (0 !== strpos(rawurldecode($string), $prefix)) {
  1906. return false;
  1907. }
  1908. $len = strlen($prefix);
  1909. if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) {
  1910. return $match[0];
  1911. }
  1912. return false;
  1913. }
  1914. private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
  1915. {
  1916. if (self::$requestFactory) {
  1917. $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content);
  1918. if (!$request instanceof Request) {
  1919. throw new \LogicException('The Request factory must return an instance of Symfony\\Component\\HttpFoundation\\Request.');
  1920. }
  1921. return $request;
  1922. }
  1923. return new static($query, $request, $attributes, $cookies, $files, $server, $content);
  1924. }
  1925. }
  1926. namespace Symfony\Component\HttpFoundation;
  1927. class ParameterBag implements \IteratorAggregate, \Countable
  1928. {
  1929. protected $parameters;
  1930. public function __construct(array $parameters = array())
  1931. {
  1932. $this->parameters = $parameters;
  1933. }
  1934. public function all()
  1935. {
  1936. return $this->parameters;
  1937. }
  1938. public function keys()
  1939. {
  1940. return array_keys($this->parameters);
  1941. }
  1942. public function replace(array $parameters = array())
  1943. {
  1944. $this->parameters = $parameters;
  1945. }
  1946. public function add(array $parameters = array())
  1947. {
  1948. $this->parameters = array_replace($this->parameters, $parameters);
  1949. }
  1950. public function get($path, $default = null, $deep = false)
  1951. {
  1952. if (!$deep || false === ($pos = strpos($path, '['))) {
  1953. return array_key_exists($path, $this->parameters) ? $this->parameters[$path] : $default;
  1954. }
  1955. $root = substr($path, 0, $pos);
  1956. if (!array_key_exists($root, $this->parameters)) {
  1957. return $default;
  1958. }
  1959. $value = $this->parameters[$root];
  1960. $currentKey = null;
  1961. for ($i = $pos, $c = strlen($path); $i < $c; $i++) {
  1962. $char = $path[$i];
  1963. if ('[' === $char) {
  1964. if (null !== $currentKey) {
  1965. throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "[" at position %d.', $i));
  1966. }
  1967. $currentKey = '';
  1968. } elseif (']' === $char) {
  1969. if (null === $currentKey) {
  1970. throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "]" at position %d.', $i));
  1971. }
  1972. if (!is_array($value) || !array_key_exists($currentKey, $value)) {
  1973. return $default;
  1974. }
  1975. $value = $value[$currentKey];
  1976. $currentKey = null;
  1977. } else {
  1978. if (null === $currentKey) {
  1979. throw new \InvalidArgumentException(sprintf('Malformed path. Unexpected "%s" at position %d.', $char, $i));
  1980. }
  1981. $currentKey .= $char;
  1982. }
  1983. }
  1984. if (null !== $currentKey) {
  1985. throw new \InvalidArgumentException(sprintf('Malformed path. Path must end with "]".'));
  1986. }
  1987. return $value;
  1988. }
  1989. public function set($key, $value)
  1990. {
  1991. $this->parameters[$key] = $value;
  1992. }
  1993. public function has($key)
  1994. {
  1995. return array_key_exists($key, $this->parameters);
  1996. }
  1997. public function remove($key)
  1998. {
  1999. unset($this->parameters[$key]);
  2000. }
  2001. public function getAlpha($key, $default = '', $deep = false)
  2002. {
  2003. return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default, $deep));
  2004. }
  2005. public function getAlnum($key, $default = '', $deep = false)
  2006. {
  2007. return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default, $deep));
  2008. }
  2009. public function getDigits($key, $default = '', $deep = false)
  2010. {
  2011. return str_replace(array('-', '+'), '', $this->filter($key, $default, $deep, FILTER_SANITIZE_NUMBER_INT));
  2012. }
  2013. public function getInt($key, $default = 0, $deep = false)
  2014. {
  2015. return (int) $this->get($key, $default, $deep);
  2016. }
  2017. public function filter($key, $default = null, $deep = false, $filter = FILTER_DEFAULT, $options = array())
  2018. {
  2019. $value = $this->get($key, $default, $deep);
  2020. if (!is_array($options) && $options) {
  2021. $options = array('flags' => $options);
  2022. }
  2023. if (is_array($value) && !isset($options['flags'])) {
  2024. $options['flags'] = FILTER_REQUIRE_ARRAY;
  2025. }
  2026. return filter_var($value, $filter, $options);
  2027. }
  2028. public function getIterator()
  2029. {
  2030. return new \ArrayIterator($this->parameters);
  2031. }
  2032. public function count()
  2033. {
  2034. return count($this->parameters);
  2035. }
  2036. }
  2037. namespace Symfony\Component\HttpFoundation;
  2038. use Symfony\Component\HttpFoundation\File\UploadedFile;
  2039. class FileBag extends ParameterBag
  2040. {
  2041. private static $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type');
  2042. public function __construct(array $parameters = array())
  2043. {
  2044. $this->replace($parameters);
  2045. }
  2046. public function replace(array $files = array())
  2047. {
  2048. $this->parameters = array();
  2049. $this->add($files);
  2050. }
  2051. public function set($key, $value)
  2052. {
  2053. if (!is_array($value) && !$value instanceof UploadedFile) {
  2054. throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.');
  2055. }
  2056. parent::set($key, $this->convertFileInformation($value));
  2057. }
  2058. public function add(array $files = array())
  2059. {
  2060. foreach ($files as $key => $file) {
  2061. $this->set($key, $file);
  2062. }
  2063. }
  2064. protected function convertFileInformation($file)
  2065. {
  2066. if ($file instanceof UploadedFile) {
  2067. return $file;
  2068. }
  2069. $file = $this->fixPhpFilesArray($file);
  2070. if (is_array($file)) {
  2071. $keys = array_keys($file);
  2072. sort($keys);
  2073. if ($keys == self::$fileKeys) {
  2074. if (UPLOAD_ERR_NO_FILE == $file['error']) {
  2075. $file = null;
  2076. } else {
  2077. $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']);
  2078. }
  2079. } else {
  2080. $file = array_map(array($this, 'convertFileInformation'), $file);
  2081. }
  2082. }
  2083. return $file;
  2084. }
  2085. protected function fixPhpFilesArray($data)
  2086. {
  2087. if (!is_array($data)) {
  2088. return $data;
  2089. }
  2090. $keys = array_keys($data);
  2091. sort($keys);
  2092. if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) {
  2093. return $data;
  2094. }
  2095. $files = $data;
  2096. foreach (self::$fileKeys as $k) {
  2097. unset($files[$k]);
  2098. }
  2099. foreach (array_keys($data['name']) as $key) {
  2100. $files[$key] = $this->fixPhpFilesArray(array('error' => $data['error'][$key], 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key]));
  2101. }
  2102. return $files;
  2103. }
  2104. }
  2105. namespace Symfony\Component\HttpFoundation;
  2106. class ServerBag extends ParameterBag
  2107. {
  2108. public function getHeaders()
  2109. {
  2110. $headers = array();
  2111. $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
  2112. foreach ($this->parameters as $key => $value) {
  2113. if (0 === strpos($key, 'HTTP_')) {
  2114. $headers[substr($key, 5)] = $value;
  2115. } elseif (isset($contentHeaders[$key])) {
  2116. $headers[$key] = $value;
  2117. }
  2118. }
  2119. if (isset($this->parameters['PHP_AUTH_USER'])) {
  2120. $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER'];
  2121. $headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : '';
  2122. } else {
  2123. $authorizationHeader = null;
  2124. if (isset($this->parameters['HTTP_AUTHORIZATION'])) {
  2125. $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION'];
  2126. } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) {
  2127. $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION'];
  2128. }
  2129. if (null !== $authorizationHeader) {
  2130. if (0 === stripos($authorizationHeader, 'basic')) {
  2131. $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
  2132. if (count($exploded) == 2) {
  2133. list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
  2134. }
  2135. } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && 0 === stripos($authorizationHeader, 'digest')) {
  2136. $headers['PHP_AUTH_DIGEST'] = $authorizationHeader;
  2137. $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader;
  2138. }
  2139. }
  2140. }
  2141. if (isset($headers['PHP_AUTH_USER'])) {
  2142. $headers['AUTHORIZATION'] = 'Basic ' . base64_encode($headers['PHP_AUTH_USER'] . ':' . $headers['PHP_AUTH_PW']);
  2143. } elseif (isset($headers['PHP_AUTH_DIGEST'])) {
  2144. $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST'];
  2145. }
  2146. return $headers;
  2147. }
  2148. }
  2149. namespace Symfony\Component\HttpFoundation;
  2150. class HeaderBag implements \IteratorAggregate, \Countable
  2151. {
  2152. protected $headers = array();
  2153. protected $cacheControl = array();
  2154. public function __construct(array $headers = array())
  2155. {
  2156. foreach ($headers as $key => $values) {
  2157. $this->set($key, $values);
  2158. }
  2159. }
  2160. public function __toString()
  2161. {
  2162. if (!$this->headers) {
  2163. return '';
  2164. }
  2165. $max = max(array_map('strlen', array_keys($this->headers))) + 1;
  2166. $content = '';
  2167. ksort($this->headers);
  2168. foreach ($this->headers as $name => $values) {
  2169. $name = implode('-', array_map('ucfirst', explode('-', $name)));
  2170. foreach ($values as $value) {
  2171. $content .= sprintf("%-{$max}s %s\r\n", $name . ':', $value);
  2172. }
  2173. }
  2174. return $content;
  2175. }
  2176. public function all()
  2177. {
  2178. return $this->headers;
  2179. }
  2180. public function keys()
  2181. {
  2182. return array_keys($this->headers);
  2183. }
  2184. public function replace(array $headers = array())
  2185. {
  2186. $this->headers = array();
  2187. $this->add($headers);
  2188. }
  2189. public function add(array $headers)
  2190. {
  2191. foreach ($headers as $key => $values) {
  2192. $this->set($key, $values);
  2193. }
  2194. }
  2195. public function get($key, $default = null, $first = true)
  2196. {
  2197. $key = strtr(strtolower($key), '_', '-');
  2198. if (!array_key_exists($key, $this->headers)) {
  2199. if (null === $default) {
  2200. return $first ? null : array();
  2201. }
  2202. return $first ? $default : array($default);
  2203. }
  2204. if ($first) {
  2205. return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
  2206. }
  2207. return $this->headers[$key];
  2208. }
  2209. public function set($key, $values, $replace = true)
  2210. {
  2211. $key = strtr(strtolower($key), '_', '-');
  2212. $values = array_values((array) $values);
  2213. if (true === $replace || !isset($this->headers[$key])) {
  2214. $this->headers[$key] = $values;
  2215. } else {
  2216. $this->headers[$key] = array_merge($this->headers[$key], $values);
  2217. }
  2218. if ('cache-control' === $key) {
  2219. $this->cacheControl = $this->parseCacheControl($values[0]);
  2220. }
  2221. }
  2222. public function has($key)
  2223. {
  2224. return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
  2225. }
  2226. public function contains($key, $value)
  2227. {
  2228. return in_array($value, $this->get($key, null, false));
  2229. }
  2230. public function remove($key)
  2231. {
  2232. $key = strtr(strtolower($key), '_', '-');
  2233. unset($this->headers[$key]);
  2234. if ('cache-control' === $key) {
  2235. $this->cacheControl = array();
  2236. }
  2237. }
  2238. public function getDate($key, \DateTime $default = null)
  2239. {
  2240. if (null === ($value = $this->get($key))) {
  2241. return $default;
  2242. }
  2243. if (false === ($date = \DateTime::createFromFormat(DATE_RFC2822, $value))) {
  2244. throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
  2245. }
  2246. return $date;
  2247. }
  2248. public function addCacheControlDirective($key, $value = true)
  2249. {
  2250. $this->cacheControl[$key] = $value;
  2251. $this->set('Cache-Control', $this->getCacheControlHeader());
  2252. }
  2253. public function hasCacheControlDirective($key)
  2254. {
  2255. return array_key_exists($key, $this->cacheControl);
  2256. }
  2257. public function getCacheControlDirective($key)
  2258. {
  2259. return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
  2260. }
  2261. public function removeCacheControlDirective($key)
  2262. {
  2263. unset($this->cacheControl[$key]);
  2264. $this->set('Cache-Control', $this->getCacheControlHeader());
  2265. }
  2266. public function getIterator()
  2267. {
  2268. return new \ArrayIterator($this->headers);
  2269. }
  2270. public function count()
  2271. {
  2272. return count($this->headers);
  2273. }
  2274. protected function getCacheControlHeader()
  2275. {
  2276. $parts = array();
  2277. ksort($this->cacheControl);
  2278. foreach ($this->cacheControl as $key => $value) {
  2279. if (true === $value) {
  2280. $parts[] = $key;
  2281. } else {
  2282. if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
  2283. $value = '"' . $value . '"';
  2284. }
  2285. $parts[] = "{$key}={$value}";
  2286. }
  2287. }
  2288. return implode(', ', $parts);
  2289. }
  2290. protected function parseCacheControl($header)
  2291. {
  2292. $cacheControl = array();
  2293. preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\\s*(?:=(?:"([^"]*)"|([^ \\t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
  2294. foreach ($matches as $match) {
  2295. $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true);
  2296. }
  2297. return $cacheControl;
  2298. }
  2299. }
  2300. namespace Symfony\Component\HttpFoundation\Session;
  2301. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  2302. interface SessionInterface
  2303. {
  2304. public function start();
  2305. public function getId();
  2306. public function setId($id);
  2307. public function getName();
  2308. public function setName($name);
  2309. public function invalidate($lifetime = null);
  2310. public function migrate($destroy = false, $lifetime = null);
  2311. public function save();
  2312. public function has($name);
  2313. public function get($name, $default = null);
  2314. public function set($name, $value);
  2315. public function all();
  2316. public function replace(array $attributes);
  2317. public function remove($name);
  2318. public function clear();
  2319. public function isStarted();
  2320. public function registerBag(SessionBagInterface $bag);
  2321. public function getBag($name);
  2322. public function getMetadataBag();
  2323. }
  2324. namespace Symfony\Component\HttpFoundation\Session;
  2325. interface SessionBagInterface
  2326. {
  2327. public function getName();
  2328. public function initialize(array &$array);
  2329. public function getStorageKey();
  2330. public function clear();
  2331. }
  2332. namespace Symfony\Component\HttpFoundation\Session\Attribute;
  2333. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  2334. interface AttributeBagInterface extends SessionBagInterface
  2335. {
  2336. public function has($name);
  2337. public function get($name, $default = null);
  2338. public function set($name, $value);
  2339. public function all();
  2340. public function replace(array $attributes);
  2341. public function remove($name);
  2342. }
  2343. namespace Symfony\Component\HttpFoundation\Session\Attribute;
  2344. class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable
  2345. {
  2346. private $name = 'attributes';
  2347. private $storageKey;
  2348. protected $attributes = array();
  2349. public function __construct($storageKey = '_sf2_attributes')
  2350. {
  2351. $this->storageKey = $storageKey;
  2352. }
  2353. public function getName()
  2354. {
  2355. return $this->name;
  2356. }
  2357. public function setName($name)
  2358. {
  2359. $this->name = $name;
  2360. }
  2361. public function initialize(array &$attributes)
  2362. {
  2363. $this->attributes =& $attributes;
  2364. }
  2365. public function getStorageKey()
  2366. {
  2367. return $this->storageKey;
  2368. }
  2369. public function has($name)
  2370. {
  2371. return array_key_exists($name, $this->attributes);
  2372. }
  2373. public function get($name, $default = null)
  2374. {
  2375. return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default;
  2376. }
  2377. public function set($name, $value)
  2378. {
  2379. $this->attributes[$name] = $value;
  2380. }
  2381. public function all()
  2382. {
  2383. return $this->attributes;
  2384. }
  2385. public function replace(array $attributes)
  2386. {
  2387. $this->attributes = array();
  2388. foreach ($attributes as $key => $value) {
  2389. $this->set($key, $value);
  2390. }
  2391. }
  2392. public function remove($name)
  2393. {
  2394. $retval = null;
  2395. if (array_key_exists($name, $this->attributes)) {
  2396. $retval = $this->attributes[$name];
  2397. unset($this->attributes[$name]);
  2398. }
  2399. return $retval;
  2400. }
  2401. public function clear()
  2402. {
  2403. $return = $this->attributes;
  2404. $this->attributes = array();
  2405. return $return;
  2406. }
  2407. public function getIterator()
  2408. {
  2409. return new \ArrayIterator($this->attributes);
  2410. }
  2411. public function count()
  2412. {
  2413. return count($this->attributes);
  2414. }
  2415. }
  2416. namespace Symfony\Component\HttpFoundation\Session\Storage;
  2417. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  2418. class MetadataBag implements SessionBagInterface
  2419. {
  2420. const CREATED = 'c';
  2421. const UPDATED = 'u';
  2422. const LIFETIME = 'l';
  2423. private $name = '__metadata';
  2424. private $storageKey;
  2425. protected $meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0);
  2426. private $lastUsed;
  2427. private $updateThreshold;
  2428. public function __construct($storageKey = '_sf2_meta', $updateThreshold = 0)
  2429. {
  2430. $this->storageKey = $storageKey;
  2431. $this->updateThreshold = $updateThreshold;
  2432. }
  2433. public function initialize(array &$array)
  2434. {
  2435. $this->meta =& $array;
  2436. if (isset($array[self::CREATED])) {
  2437. $this->lastUsed = $this->meta[self::UPDATED];
  2438. $timeStamp = time();
  2439. if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) {
  2440. $this->meta[self::UPDATED] = $timeStamp;
  2441. }
  2442. } else {
  2443. $this->stampCreated();
  2444. }
  2445. }
  2446. public function getLifetime()
  2447. {
  2448. return $this->meta[self::LIFETIME];
  2449. }
  2450. public function stampNew($lifetime = null)
  2451. {
  2452. $this->stampCreated($lifetime);
  2453. }
  2454. public function getStorageKey()
  2455. {
  2456. return $this->storageKey;
  2457. }
  2458. public function getCreated()
  2459. {
  2460. return $this->meta[self::CREATED];
  2461. }
  2462. public function getLastUsed()
  2463. {
  2464. return $this->lastUsed;
  2465. }
  2466. public function clear()
  2467. {
  2468. }
  2469. public function getName()
  2470. {
  2471. return $this->name;
  2472. }
  2473. public function setName($name)
  2474. {
  2475. $this->name = $name;
  2476. }
  2477. private function stampCreated($lifetime = null)
  2478. {
  2479. $timeStamp = time();
  2480. $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp;
  2481. $this->meta[self::LIFETIME] = null === $lifetime ? ini_get('session.cookie_lifetime') : $lifetime;
  2482. }
  2483. }
  2484. namespace Symfony\Component\HttpFoundation;
  2485. class AcceptHeaderItem
  2486. {
  2487. private $value;
  2488. private $quality = 1.0;
  2489. private $index = 0;
  2490. private $attributes = array();
  2491. public function __construct($value, array $attributes = array())
  2492. {
  2493. $this->value = $value;
  2494. foreach ($attributes as $name => $value) {
  2495. $this->setAttribute($name, $value);
  2496. }
  2497. }
  2498. public static function fromString($itemValue)
  2499. {
  2500. $bits = preg_split('/\\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  2501. $value = array_shift($bits);
  2502. $attributes = array();
  2503. $lastNullAttribute = null;
  2504. foreach ($bits as $bit) {
  2505. if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) {
  2506. $attributes[$lastNullAttribute] = substr($bit, 1, -1);
  2507. } elseif ('=' === $end) {
  2508. $lastNullAttribute = $bit = substr($bit, 0, -1);
  2509. $attributes[$bit] = null;
  2510. } else {
  2511. $parts = explode('=', $bit);
  2512. $attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : '';
  2513. }
  2514. }
  2515. return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes);
  2516. }
  2517. public function __toString()
  2518. {
  2519. $string = $this->value . ($this->quality < 1 ? ';q=' . $this->quality : '');
  2520. if (count($this->attributes) > 0) {
  2521. $string .= ';' . implode(';', array_map(function ($name, $value) {
  2522. return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value);
  2523. }, array_keys($this->attributes), $this->attributes));
  2524. }
  2525. return $string;
  2526. }
  2527. public function setValue($value)
  2528. {
  2529. $this->value = $value;
  2530. return $this;
  2531. }
  2532. public function getValue()
  2533. {
  2534. return $this->value;
  2535. }
  2536. public function setQuality($quality)
  2537. {
  2538. $this->quality = $quality;
  2539. return $this;
  2540. }
  2541. public function getQuality()
  2542. {
  2543. return $this->quality;
  2544. }
  2545. public function setIndex($index)
  2546. {
  2547. $this->index = $index;
  2548. return $this;
  2549. }
  2550. public function getIndex()
  2551. {
  2552. return $this->index;
  2553. }
  2554. public function hasAttribute($name)
  2555. {
  2556. return isset($this->attributes[$name]);
  2557. }
  2558. public function getAttribute($name, $default = null)
  2559. {
  2560. return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
  2561. }
  2562. public function getAttributes()
  2563. {
  2564. return $this->attributes;
  2565. }
  2566. public function setAttribute($name, $value)
  2567. {
  2568. if ('q' === $name) {
  2569. $this->quality = (double) $value;
  2570. } else {
  2571. $this->attributes[$name] = (string) $value;
  2572. }
  2573. return $this;
  2574. }
  2575. }
  2576. namespace Symfony\Component\HttpFoundation;
  2577. class AcceptHeader
  2578. {
  2579. private $items = array();
  2580. private $sorted = true;
  2581. public function __construct(array $items)
  2582. {
  2583. foreach ($items as $item) {
  2584. $this->add($item);
  2585. }
  2586. }
  2587. public static function fromString($headerValue)
  2588. {
  2589. $index = 0;
  2590. return new self(array_map(function ($itemValue) use(&$index) {
  2591. $item = AcceptHeaderItem::fromString($itemValue);
  2592. $item->setIndex($index++);
  2593. return $item;
  2594. }, preg_split('/\\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)));
  2595. }
  2596. public function __toString()
  2597. {
  2598. return implode(',', $this->items);
  2599. }
  2600. public function has($value)
  2601. {
  2602. return isset($this->items[$value]);
  2603. }
  2604. public function get($value)
  2605. {
  2606. return isset($this->items[$value]) ? $this->items[$value] : null;
  2607. }
  2608. public function add(AcceptHeaderItem $item)
  2609. {
  2610. $this->items[$item->getValue()] = $item;
  2611. $this->sorted = false;
  2612. return $this;
  2613. }
  2614. public function all()
  2615. {
  2616. $this->sort();
  2617. return $this->items;
  2618. }
  2619. public function filter($pattern)
  2620. {
  2621. return new self(array_filter($this->items, function (AcceptHeaderItem $item) use($pattern) {
  2622. return preg_match($pattern, $item->getValue());
  2623. }));
  2624. }
  2625. public function first()
  2626. {
  2627. $this->sort();
  2628. return !empty($this->items) ? reset($this->items) : null;
  2629. }
  2630. private function sort()
  2631. {
  2632. if (!$this->sorted) {
  2633. uasort($this->items, function ($a, $b) {
  2634. $qA = $a->getQuality();
  2635. $qB = $b->getQuality();
  2636. if ($qA === $qB) {
  2637. return $a->getIndex() > $b->getIndex() ? 1 : -1;
  2638. }
  2639. return $qA > $qB ? -1 : 1;
  2640. });
  2641. $this->sorted = true;
  2642. }
  2643. }
  2644. }
  2645. namespace Symfony\Component\Debug;
  2646. use Symfony\Component\HttpFoundation\Response;
  2647. use Symfony\Component\Debug\Exception\FlattenException;
  2648. use Symfony\Component\Debug\Exception\OutOfMemoryException;
  2649. if (!defined('ENT_SUBSTITUTE')) {
  2650. define('ENT_SUBSTITUTE', 8);
  2651. }
  2652. class ExceptionHandler
  2653. {
  2654. private $debug;
  2655. private $charset;
  2656. private $handler;
  2657. private $caughtOutput = 0;
  2658. public function __construct($debug = true, $charset = 'UTF-8')
  2659. {
  2660. $this->debug = $debug;
  2661. $this->charset = $charset;
  2662. }
  2663. public static function register($debug = true)
  2664. {
  2665. $handler = new static($debug);
  2666. set_exception_handler(array($handler, 'handle'));
  2667. return $handler;
  2668. }
  2669. public function setHandler($handler)
  2670. {
  2671. if (isset($handler) && !is_callable($handler)) {
  2672. throw new \LogicException('The exception handler must be a valid PHP callable.');
  2673. }
  2674. $old = $this->handler;
  2675. $this->handler = $handler;
  2676. return $old;
  2677. }
  2678. public function handle(\Exception $exception)
  2679. {
  2680. if ($exception instanceof OutOfMemoryException) {
  2681. $this->sendPhpResponse($exception);
  2682. return;
  2683. }
  2684. $caughtOutput = 0;
  2685. $this->caughtOutput = false;
  2686. ob_start(array($this, 'catchOutput'));
  2687. try {
  2688. if (class_exists('Symfony\\Component\\HttpFoundation\\Response')) {
  2689. $response = $this->createResponse($exception);
  2690. $response->sendHeaders();
  2691. $response->sendContent();
  2692. } else {
  2693. $this->sendPhpResponse($exception);
  2694. }
  2695. } catch (\Exception $e) {
  2696. }
  2697. if (false === $this->caughtOutput) {
  2698. ob_end_clean();
  2699. }
  2700. if (isset($this->caughtOutput[0])) {
  2701. ob_start(array($this, 'cleanOutput'));
  2702. echo $this->caughtOutput;
  2703. $caughtOutput = ob_get_length();
  2704. }
  2705. $this->caughtOutput = 0;
  2706. if (!empty($this->handler)) {
  2707. try {
  2708. call_user_func($this->handler, $exception);
  2709. if ($caughtOutput) {
  2710. $this->caughtOutput = $caughtOutput;
  2711. }
  2712. } catch (\Exception $e) {
  2713. if (!$caughtOutput) {
  2714. throw $exception;
  2715. }
  2716. }
  2717. }
  2718. }
  2719. public function sendPhpResponse($exception)
  2720. {
  2721. if (!$exception instanceof FlattenException) {
  2722. $exception = FlattenException::create($exception);
  2723. }
  2724. if (!headers_sent()) {
  2725. header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
  2726. foreach ($exception->getHeaders() as $name => $value) {
  2727. header($name . ': ' . $value, false);
  2728. }
  2729. }
  2730. echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
  2731. }
  2732. public function createResponse($exception)
  2733. {
  2734. if (!$exception instanceof FlattenException) {
  2735. $exception = FlattenException::create($exception);
  2736. }
  2737. return new Response($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders());
  2738. }
  2739. public function getContent(FlattenException $exception)
  2740. {
  2741. switch ($exception->getStatusCode()) {
  2742. case 404:
  2743. $title = 'Sorry, the page you are looking for could not be found.';
  2744. break;
  2745. default:
  2746. $title = 'Whoops, looks like something went wrong.';
  2747. }
  2748. $content = '';
  2749. if ($this->debug) {
  2750. try {
  2751. $count = count($exception->getAllPrevious());
  2752. $total = $count + 1;
  2753. foreach ($exception->toArray() as $position => $e) {
  2754. $ind = $count - $position + 1;
  2755. $class = $this->abbrClass($e['class']);
  2756. $message = nl2br($e['message']);
  2757. $content .= sprintf(' <div class="block_exception clear_fix">
  2758. <h2><span>%d/%d</span> %s: %s</h2>
  2759. </div>
  2760. <div class="block">
  2761. <ol class="traces list_exception">', $ind, $total, $class, $message);
  2762. foreach ($e['trace'] as $trace) {
  2763. $content .= ' <li>';
  2764. if ($trace['function']) {
  2765. $content .= sprintf('at %s%s%s(%s)', $this->abbrClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
  2766. }
  2767. if (isset($trace['file']) && isset($trace['line'])) {
  2768. if ($linkFormat = ini_get('xdebug.file_link_format')) {
  2769. $link = str_replace(array('%f', '%l'), array($trace['file'], $trace['line']), $linkFormat);
  2770. $content .= sprintf(' in <a href="%s" title="Go to source">%s line %s</a>', $link, $trace['file'], $trace['line']);
  2771. } else {
  2772. $content .= sprintf(' in %s line %s', $trace['file'], $trace['line']);
  2773. }
  2774. }
  2775. $content .= '</li>
  2776. ';
  2777. }
  2778. $content .= ' </ol>
  2779. </div>
  2780. ';
  2781. }
  2782. } catch (\Exception $e) {
  2783. if ($this->debug) {
  2784. $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($exception), $exception->getMessage());
  2785. } else {
  2786. $title = 'Whoops, looks like something went wrong.';
  2787. }
  2788. }
  2789. }
  2790. return " <div id=\"sf-resetcontent\" class=\"sf-reset\">\n <h1>{$title}</h1>\n {$content}\n </div>";
  2791. }
  2792. public function getStylesheet(FlattenException $exception)
  2793. {
  2794. return ' .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
  2795. .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
  2796. .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
  2797. .sf-reset .clear_fix { display:inline-block; }
  2798. .sf-reset * html .clear_fix { height:1%; }
  2799. .sf-reset .clear_fix { display:block; }
  2800. .sf-reset, .sf-reset .block { margin: auto }
  2801. .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
  2802. .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
  2803. .sf-reset strong { font-weight:bold; }
  2804. .sf-reset a { color:#6c6159; }
  2805. .sf-reset a img { border:none; }
  2806. .sf-reset a:hover { text-decoration:underline; }
  2807. .sf-reset em { font-style:italic; }
  2808. .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
  2809. .sf-reset h2 span { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; }
  2810. .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
  2811. .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
  2812. -webkit-border-bottom-right-radius: 16px;
  2813. -webkit-border-bottom-left-radius: 16px;
  2814. -moz-border-radius-bottomright: 16px;
  2815. -moz-border-radius-bottomleft: 16px;
  2816. border-bottom-right-radius: 16px;
  2817. border-bottom-left-radius: 16px;
  2818. border-bottom:1px solid #ccc;
  2819. border-right:1px solid #ccc;
  2820. border-left:1px solid #ccc;
  2821. }
  2822. .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
  2823. -webkit-border-top-left-radius: 16px;
  2824. -webkit-border-top-right-radius: 16px;
  2825. -moz-border-radius-topleft: 16px;
  2826. -moz-border-radius-topright: 16px;
  2827. border-top-left-radius: 16px;
  2828. border-top-right-radius: 16px;
  2829. border-top:1px solid #ccc;
  2830. border-right:1px solid #ccc;
  2831. border-left:1px solid #ccc;
  2832. overflow: hidden;
  2833. word-wrap: break-word;
  2834. }
  2835. .sf-reset li a { background:none; color:#868686; text-decoration:none; }
  2836. .sf-reset li a:hover { background:none; color:#313131; text-decoration:underline; }
  2837. .sf-reset ol { padding: 10px 0; }
  2838. .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
  2839. -webkit-border-radius: 10px;
  2840. -moz-border-radius: 10px;
  2841. border-radius: 10px;
  2842. border: 1px solid #ccc;
  2843. }';
  2844. }
  2845. private function decorate($content, $css)
  2846. {
  2847. return "<!DOCTYPE html>\n<html>\n <head>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>\n <meta name=\"robots\" content=\"noindex,nofollow\" />\n <style>\n /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */\n html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}\n\n html { background: #eee; padding: 10px }\n img { border: 0; }\n #sf-resetcontent { width:970px; margin:0 auto; }\n {$css}\n </style>\n </head>\n <body>\n {$content}\n </body>\n</html>";
  2848. }
  2849. private function abbrClass($class)
  2850. {
  2851. $parts = explode('\\', $class);
  2852. return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
  2853. }
  2854. private function formatArgs(array $args)
  2855. {
  2856. $result = array();
  2857. foreach ($args as $key => $item) {
  2858. if ('object' === $item[0]) {
  2859. $formattedValue = sprintf('<em>object</em>(%s)', $this->abbrClass($item[1]));
  2860. } elseif ('array' === $item[0]) {
  2861. $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
  2862. } elseif ('string' === $item[0]) {
  2863. $formattedValue = sprintf('\'%s\'', htmlspecialchars($item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset));
  2864. } elseif ('null' === $item[0]) {
  2865. $formattedValue = '<em>null</em>';
  2866. } elseif ('boolean' === $item[0]) {
  2867. $formattedValue = '<em>' . strtolower(var_export($item[1], true)) . '</em>';
  2868. } elseif ('resource' === $item[0]) {
  2869. $formattedValue = '<em>resource</em>';
  2870. } else {
  2871. $formattedValue = str_replace('
  2872. ', '', var_export(htmlspecialchars((string) $item[1], ENT_QUOTES | ENT_SUBSTITUTE, $this->charset), true));
  2873. }
  2874. $result[] = is_int($key) ? $formattedValue : sprintf('\'%s\' => %s', $key, $formattedValue);
  2875. }
  2876. return implode(', ', $result);
  2877. }
  2878. public function catchOutput($buffer)
  2879. {
  2880. $this->caughtOutput = $buffer;
  2881. return '';
  2882. }
  2883. public function cleanOutput($buffer)
  2884. {
  2885. if ($this->caughtOutput) {
  2886. $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtOutput);
  2887. if (isset($cleanBuffer[0])) {
  2888. $buffer = $cleanBuffer;
  2889. }
  2890. }
  2891. return $buffer;
  2892. }
  2893. }
  2894. namespace Illuminate\Support;
  2895. use ReflectionClass;
  2896. abstract class ServiceProvider
  2897. {
  2898. protected $app;
  2899. protected $defer = false;
  2900. public function __construct($app)
  2901. {
  2902. $this->app = $app;
  2903. }
  2904. public function boot()
  2905. {
  2906. }
  2907. public abstract function register();
  2908. public function package($package, $namespace = null, $path = null)
  2909. {
  2910. $namespace = $this->getPackageNamespace($package, $namespace);
  2911. $path = $path ?: $this->guessPackagePath();
  2912. $config = $path . '/config';
  2913. if ($this->app['files']->isDirectory($config)) {
  2914. $this->app['config']->package($package, $config, $namespace);
  2915. }
  2916. $lang = $path . '/lang';
  2917. if ($this->app['files']->isDirectory($lang)) {
  2918. $this->app['translator']->addNamespace($namespace, $lang);
  2919. }
  2920. $appView = $this->getAppViewPath($package);
  2921. if ($this->app['files']->isDirectory($appView)) {
  2922. $this->app['view']->addNamespace($namespace, $appView);
  2923. }
  2924. $view = $path . '/views';
  2925. if ($this->app['files']->isDirectory($view)) {
  2926. $this->app['view']->addNamespace($namespace, $view);
  2927. }
  2928. }
  2929. public function guessPackagePath()
  2930. {
  2931. $path = with(new ReflectionClass($this))->getFileName();
  2932. return realpath(dirname($path) . '/../../');
  2933. }
  2934. protected function getPackageNamespace($package, $namespace)
  2935. {
  2936. if (is_null($namespace)) {
  2937. list($vendor, $namespace) = explode('/', $package);
  2938. }
  2939. return $namespace;
  2940. }
  2941. public function commands($commands)
  2942. {
  2943. $commands = is_array($commands) ? $commands : func_get_args();
  2944. $events = $this->app['events'];
  2945. $events->listen('artisan.start', function ($artisan) use($commands) {
  2946. $artisan->resolveCommands($commands);
  2947. });
  2948. }
  2949. protected function getAppViewPath($package)
  2950. {
  2951. return $this->app['path'] . "/views/packages/{$package}";
  2952. }
  2953. public function provides()
  2954. {
  2955. return array();
  2956. }
  2957. public function when()
  2958. {
  2959. return array();
  2960. }
  2961. public function isDeferred()
  2962. {
  2963. return $this->defer;
  2964. }
  2965. }
  2966. namespace Illuminate\Exception;
  2967. use Whoops\Run;
  2968. use Whoops\Handler\PrettyPageHandler;
  2969. use Whoops\Handler\JsonResponseHandler;
  2970. use Illuminate\Support\ServiceProvider;
  2971. class ExceptionServiceProvider extends ServiceProvider
  2972. {
  2973. public function register()
  2974. {
  2975. $this->registerDisplayers();
  2976. $this->registerHandler();
  2977. }
  2978. protected function registerDisplayers()
  2979. {
  2980. $this->registerPlainDisplayer();
  2981. $this->registerDebugDisplayer();
  2982. }
  2983. protected function registerHandler()
  2984. {
  2985. $this->app['exception'] = $this->app->share(function ($app) {
  2986. return new Handler($app, $app['exception.plain'], $app['exception.debug']);
  2987. });
  2988. }
  2989. protected function registerPlainDisplayer()
  2990. {
  2991. $this->app['exception.plain'] = $this->app->share(function ($app) {
  2992. if ($app->runningInConsole()) {
  2993. return $app['exception.debug'];
  2994. } else {
  2995. return new PlainDisplayer();
  2996. }
  2997. });
  2998. }
  2999. protected function registerDebugDisplayer()
  3000. {
  3001. $this->registerWhoops();
  3002. $this->app['exception.debug'] = $this->app->share(function ($app) {
  3003. return new WhoopsDisplayer($app['whoops'], $app->runningInConsole());
  3004. });
  3005. }
  3006. protected function registerWhoops()
  3007. {
  3008. $this->registerWhoopsHandler();
  3009. $this->app['whoops'] = $this->app->share(function ($app) {
  3010. with($whoops = new Run())->allowQuit(false);
  3011. $whoops->writeToOutput(false);
  3012. return $whoops->pushHandler($app['whoops.handler']);
  3013. });
  3014. }
  3015. protected function registerWhoopsHandler()
  3016. {
  3017. if ($this->shouldReturnJson()) {
  3018. $this->app['whoops.handler'] = $this->app->share(function () {
  3019. return new JsonResponseHandler();
  3020. });
  3021. } else {
  3022. $this->registerPrettyWhoopsHandler();
  3023. }
  3024. }
  3025. protected function shouldReturnJson()
  3026. {
  3027. return $this->app->runningInConsole() || $this->requestWantsJson();
  3028. }
  3029. protected function requestWantsJson()
  3030. {
  3031. return $this->app['request']->ajax() || $this->app['request']->wantsJson();
  3032. }
  3033. protected function registerPrettyWhoopsHandler()
  3034. {
  3035. $this->app['whoops.handler'] = $this->app->share(function () {
  3036. with($handler = new PrettyPageHandler())->setEditor('sublime');
  3037. return $handler;
  3038. });
  3039. }
  3040. }
  3041. namespace Illuminate\Routing;
  3042. use Illuminate\Support\ServiceProvider;
  3043. class RoutingServiceProvider extends ServiceProvider
  3044. {
  3045. public function register()
  3046. {
  3047. $this->registerRouter();
  3048. $this->registerUrlGenerator();
  3049. $this->registerRedirector();
  3050. }
  3051. protected function registerRouter()
  3052. {
  3053. $this->app['router'] = $this->app->share(function ($app) {
  3054. $router = new Router($app['events'], $app);
  3055. if ($app['env'] == 'testing') {
  3056. $router->disableFilters();
  3057. }
  3058. return $router;
  3059. });
  3060. }
  3061. protected function registerUrlGenerator()
  3062. {
  3063. $this->app['url'] = $this->app->share(function ($app) {
  3064. $routes = $app['router']->getRoutes();
  3065. return new UrlGenerator($routes, $app->rebinding('request', function ($app, $request) {
  3066. $app['url']->setRequest($request);
  3067. }));
  3068. });
  3069. }
  3070. protected function registerRedirector()
  3071. {
  3072. $this->app['redirect'] = $this->app->share(function ($app) {
  3073. $redirector = new Redirector($app['url']);
  3074. if (isset($app['session.store'])) {
  3075. $redirector->setSession($app['session.store']);
  3076. }
  3077. return $redirector;
  3078. });
  3079. }
  3080. }
  3081. namespace Illuminate\Events;
  3082. use Illuminate\Support\ServiceProvider;
  3083. class EventServiceProvider extends ServiceProvider
  3084. {
  3085. public function register()
  3086. {
  3087. $this->app['events'] = $this->app->share(function ($app) {
  3088. return new Dispatcher($app);
  3089. });
  3090. }
  3091. }
  3092. namespace Illuminate\Support\Facades;
  3093. use Mockery\MockInterface;
  3094. abstract class Facade
  3095. {
  3096. protected static $app;
  3097. protected static $resolvedInstance;
  3098. public static function swap($instance)
  3099. {
  3100. static::$resolvedInstance[static::getFacadeAccessor()] = $instance;
  3101. static::$app->instance(static::getFacadeAccessor(), $instance);
  3102. }
  3103. public static function shouldReceive()
  3104. {
  3105. $name = static::getFacadeAccessor();
  3106. if (static::isMock()) {
  3107. $mock = static::$resolvedInstance[$name];
  3108. } else {
  3109. $mock = static::createFreshMockInstance($name);
  3110. }
  3111. return call_user_func_array(array($mock, 'shouldReceive'), func_get_args());
  3112. }
  3113. protected static function createFreshMockInstance($name)
  3114. {
  3115. static::$resolvedInstance[$name] = $mock = static::createMockByName($name);
  3116. if (isset(static::$app)) {
  3117. static::$app->instance($name, $mock);
  3118. }
  3119. return $mock;
  3120. }
  3121. protected static function createMockByName($name)
  3122. {
  3123. $class = static::getMockableClass($name);
  3124. return $class ? \Mockery::mock($class) : \Mockery::mock();
  3125. }
  3126. protected static function isMock()
  3127. {
  3128. $name = static::getFacadeAccessor();
  3129. return isset(static::$resolvedInstance[$name]) && static::$resolvedInstance[$name] instanceof MockInterface;
  3130. }
  3131. protected static function getMockableClass()
  3132. {
  3133. if ($root = static::getFacadeRoot()) {
  3134. return get_class($root);
  3135. }
  3136. }
  3137. public static function getFacadeRoot()
  3138. {
  3139. return static::resolveFacadeInstance(static::getFacadeAccessor());
  3140. }
  3141. protected static function getFacadeAccessor()
  3142. {
  3143. throw new \RuntimeException('Facade does not implement getFacadeAccessor method.');
  3144. }
  3145. protected static function resolveFacadeInstance($name)
  3146. {
  3147. if (is_object($name)) {
  3148. return $name;
  3149. }
  3150. if (isset(static::$resolvedInstance[$name])) {
  3151. return static::$resolvedInstance[$name];
  3152. }
  3153. return static::$resolvedInstance[$name] = static::$app[$name];
  3154. }
  3155. public static function clearResolvedInstance($name)
  3156. {
  3157. unset(static::$resolvedInstance[$name]);
  3158. }
  3159. public static function clearResolvedInstances()
  3160. {
  3161. static::$resolvedInstance = array();
  3162. }
  3163. public static function getFacadeApplication()
  3164. {
  3165. return static::$app;
  3166. }
  3167. public static function setFacadeApplication($app)
  3168. {
  3169. static::$app = $app;
  3170. }
  3171. public static function __callStatic($method, $args)
  3172. {
  3173. $instance = static::getFacadeRoot();
  3174. switch (count($args)) {
  3175. case 0:
  3176. return $instance->{$method}();
  3177. case 1:
  3178. return $instance->{$method}($args[0]);
  3179. case 2:
  3180. return $instance->{$method}($args[0], $args[1]);
  3181. case 3:
  3182. return $instance->{$method}($args[0], $args[1], $args[2]);
  3183. case 4:
  3184. return $instance->{$method}($args[0], $args[1], $args[2], $args[3]);
  3185. default:
  3186. return call_user_func_array(array($instance, $method), $args);
  3187. }
  3188. }
  3189. }
  3190. namespace Illuminate\Support;
  3191. use Illuminate\Support\Traits\MacroableTrait;
  3192. class Str
  3193. {
  3194. use MacroableTrait;
  3195. public static function ascii($value)
  3196. {
  3197. return \Patchwork\Utf8::toAscii($value);
  3198. }
  3199. public static function camel($value)
  3200. {
  3201. return lcfirst(static::studly($value));
  3202. }
  3203. public static function contains($haystack, $needles)
  3204. {
  3205. foreach ((array) $needles as $needle) {
  3206. if ($needle != '' && strpos($haystack, $needle) !== false) {
  3207. return true;
  3208. }
  3209. }
  3210. return false;
  3211. }
  3212. public static function endsWith($haystack, $needles)
  3213. {
  3214. foreach ((array) $needles as $needle) {
  3215. if ($needle == substr($haystack, -strlen($needle))) {
  3216. return true;
  3217. }
  3218. }
  3219. return false;
  3220. }
  3221. public static function finish($value, $cap)
  3222. {
  3223. $quoted = preg_quote($cap, '/');
  3224. return preg_replace('/(?:' . $quoted . ')+$/', '', $value) . $cap;
  3225. }
  3226. public static function is($pattern, $value)
  3227. {
  3228. if ($pattern == $value) {
  3229. return true;
  3230. }
  3231. $pattern = preg_quote($pattern, '#');
  3232. $pattern = str_replace('\\*', '.*', $pattern) . '\\z';
  3233. return (bool) preg_match('#^' . $pattern . '#', $value);
  3234. }
  3235. public static function length($value)
  3236. {
  3237. return mb_strlen($value);
  3238. }
  3239. public static function limit($value, $limit = 100, $end = '...')
  3240. {
  3241. if (mb_strlen($value) <= $limit) {
  3242. return $value;
  3243. }
  3244. return rtrim(mb_substr($value, 0, $limit, 'UTF-8')) . $end;
  3245. }
  3246. public static function lower($value)
  3247. {
  3248. return mb_strtolower($value);
  3249. }
  3250. public static function words($value, $words = 100, $end = '...')
  3251. {
  3252. preg_match('/^\\s*+(?:\\S++\\s*+){1,' . $words . '}/u', $value, $matches);
  3253. if (!isset($matches[0])) {
  3254. return $value;
  3255. }
  3256. if (strlen($value) == strlen($matches[0])) {
  3257. return $value;
  3258. }
  3259. return rtrim($matches[0]) . $end;
  3260. }
  3261. public static function parseCallback($callback, $default)
  3262. {
  3263. return static::contains($callback, '@') ? explode('@', $callback, 2) : array($callback, $default);
  3264. }
  3265. public static function plural($value, $count = 2)
  3266. {
  3267. return Pluralizer::plural($value, $count);
  3268. }
  3269. public static function random($length = 16)
  3270. {
  3271. if (function_exists('openssl_random_pseudo_bytes')) {
  3272. $bytes = openssl_random_pseudo_bytes($length * 2);
  3273. if ($bytes === false) {
  3274. throw new \RuntimeException('Unable to generate random string.');
  3275. }
  3276. return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
  3277. }
  3278. return static::quickRandom($length);
  3279. }
  3280. public static function quickRandom($length = 16)
  3281. {
  3282. $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  3283. return substr(str_shuffle(str_repeat($pool, 5)), 0, $length);
  3284. }
  3285. public static function upper($value)
  3286. {
  3287. return mb_strtoupper($value);
  3288. }
  3289. public static function title($value)
  3290. {
  3291. return mb_convert_case($value, MB_CASE_TITLE, 'UTF-8');
  3292. }
  3293. public static function singular($value)
  3294. {
  3295. return Pluralizer::singular($value);
  3296. }
  3297. public static function slug($title, $separator = '-')
  3298. {
  3299. $title = static::ascii($title);
  3300. $flip = $separator == '-' ? '_' : '-';
  3301. $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
  3302. $title = preg_replace('![^' . preg_quote($separator) . '\\pL\\pN\\s]+!u', '', mb_strtolower($title));
  3303. $title = preg_replace('![' . preg_quote($separator) . '\\s]+!u', $separator, $title);
  3304. return trim($title, $separator);
  3305. }
  3306. public static function snake($value, $delimiter = '_')
  3307. {
  3308. $replace = '$1' . $delimiter . '$2';
  3309. return ctype_lower($value) ? $value : strtolower(preg_replace('/(.)([A-Z])/', $replace, $value));
  3310. }
  3311. public static function startsWith($haystack, $needles)
  3312. {
  3313. foreach ((array) $needles as $needle) {
  3314. if ($needle != '' && strpos($haystack, $needle) === 0) {
  3315. return true;
  3316. }
  3317. }
  3318. return false;
  3319. }
  3320. public static function studly($value)
  3321. {
  3322. $value = ucwords(str_replace(array('-', '_'), ' ', $value));
  3323. return str_replace(' ', '', $value);
  3324. }
  3325. }
  3326. namespace Symfony\Component\Debug;
  3327. use Psr\Log\LogLevel;
  3328. use Psr\Log\LoggerInterface;
  3329. use Symfony\Component\Debug\Exception\ContextErrorException;
  3330. use Symfony\Component\Debug\Exception\FatalErrorException;
  3331. use Symfony\Component\Debug\Exception\OutOfMemoryException;
  3332. use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
  3333. use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
  3334. use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
  3335. use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
  3336. class ErrorHandler
  3337. {
  3338. const TYPE_DEPRECATION = -100;
  3339. private $levels = array(E_WARNING => 'Warning', E_NOTICE => 'Notice', E_USER_ERROR => 'User Error', E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_STRICT => 'Runtime Notice', E_RECOVERABLE_ERROR => 'Catchable Fatal Error', E_DEPRECATED => 'Deprecated', E_USER_DEPRECATED => 'User Deprecated', E_ERROR => 'Error', E_CORE_ERROR => 'Core Error', E_COMPILE_ERROR => 'Compile Error', E_PARSE => 'Parse Error');
  3340. private $level;
  3341. private $reservedMemory;
  3342. private $displayErrors;
  3343. private static $loggers = array();
  3344. private static $stackedErrors = array();
  3345. private static $stackedErrorLevels = array();
  3346. public static function register($level = null, $displayErrors = true)
  3347. {
  3348. $handler = new static();
  3349. $handler->setLevel($level);
  3350. $handler->setDisplayErrors($displayErrors);
  3351. ini_set('display_errors', 0);
  3352. set_error_handler(array($handler, 'handle'));
  3353. register_shutdown_function(array($handler, 'handleFatal'));
  3354. $handler->reservedMemory = str_repeat('x', 10240);
  3355. return $handler;
  3356. }
  3357. public function setLevel($level)
  3358. {
  3359. $this->level = null === $level ? error_reporting() : $level;
  3360. }
  3361. public function setDisplayErrors($displayErrors)
  3362. {
  3363. $this->displayErrors = $displayErrors;
  3364. }
  3365. public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
  3366. {
  3367. self::$loggers[$channel] = $logger;
  3368. }
  3369. public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
  3370. {
  3371. if ($level & (E_USER_DEPRECATED | E_DEPRECATED)) {
  3372. if (isset(self::$loggers['deprecation'])) {
  3373. if (self::$stackedErrorLevels) {
  3374. self::$stackedErrors[] = func_get_args();
  3375. } else {
  3376. if (version_compare(PHP_VERSION, '5.4', '<')) {
  3377. $stack = array_map(function ($row) {
  3378. unset($row['args']);
  3379. return $row;
  3380. }, array_slice(debug_backtrace(false), 0, 10));
  3381. } else {
  3382. $stack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 10);
  3383. }
  3384. self::$loggers['deprecation']->warning($message, array('type' => self::TYPE_DEPRECATION, 'stack' => $stack));
  3385. }
  3386. return true;
  3387. }
  3388. } elseif ($this->displayErrors && error_reporting() & $level && $this->level & $level) {
  3389. if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && is_array($context)) {
  3390. $c = $context;
  3391. unset($c['GLOBALS'], $context);
  3392. $context = $c;
  3393. }
  3394. $exception = sprintf('%s: %s in %s line %d', isset($this->levels[$level]) ? $this->levels[$level] : $level, $message, $file, $line);
  3395. if ($context && class_exists('Symfony\\Component\\Debug\\Exception\\ContextErrorException')) {
  3396. $exception = new ContextErrorException($exception, 0, $level, $file, $line, $context);
  3397. } else {
  3398. $exception = new \ErrorException($exception, 0, $level, $file, $line);
  3399. }
  3400. if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) {
  3401. $exception->errorHandlerCanary = new ErrorHandlerCanary();
  3402. }
  3403. throw $exception;
  3404. }
  3405. if (isset(self::$loggers['scream']) && !(error_reporting() & $level)) {
  3406. if (self::$stackedErrorLevels) {
  3407. self::$stackedErrors[] = func_get_args();
  3408. } else {
  3409. switch ($level) {
  3410. case E_USER_ERROR:
  3411. case E_RECOVERABLE_ERROR:
  3412. $logLevel = LogLevel::ERROR;
  3413. break;
  3414. case E_WARNING:
  3415. case E_USER_WARNING:
  3416. $logLevel = LogLevel::WARNING;
  3417. break;
  3418. default:
  3419. $logLevel = LogLevel::NOTICE;
  3420. break;
  3421. }
  3422. self::$loggers['scream']->log($logLevel, $message, array('type' => $level, 'file' => $file, 'line' => $line, 'scream' => error_reporting()));
  3423. }
  3424. }
  3425. return false;
  3426. }
  3427. public static function stackErrors()
  3428. {
  3429. self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
  3430. }
  3431. public static function unstackErrors()
  3432. {
  3433. $level = array_pop(self::$stackedErrorLevels);
  3434. if (null !== $level) {
  3435. $e = error_reporting($level);
  3436. if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
  3437. error_reporting($e);
  3438. }
  3439. }
  3440. if (empty(self::$stackedErrorLevels)) {
  3441. $errors = self::$stackedErrors;
  3442. self::$stackedErrors = array();
  3443. $errorHandler = set_error_handler('var_dump');
  3444. restore_error_handler();
  3445. if ($errorHandler) {
  3446. foreach ($errors as $e) {
  3447. call_user_func_array($errorHandler, $e);
  3448. }
  3449. }
  3450. }
  3451. }
  3452. public function handleFatal()
  3453. {
  3454. $this->reservedMemory = '';
  3455. gc_collect_cycles();
  3456. $error = error_get_last();
  3457. $exceptionHandler = set_exception_handler('var_dump');
  3458. restore_exception_handler();
  3459. try {
  3460. while (self::$stackedErrorLevels) {
  3461. static::unstackErrors();
  3462. }
  3463. } catch (\Exception $exception) {
  3464. if ($exceptionHandler) {
  3465. call_user_func($exceptionHandler, $exception);
  3466. return;
  3467. }
  3468. if ($this->displayErrors) {
  3469. ini_set('display_errors', 1);
  3470. }
  3471. throw $exception;
  3472. }
  3473. if (!$error || !$this->level || !($error['type'] & (E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_PARSE))) {
  3474. return;
  3475. }
  3476. if (isset(self::$loggers['emergency'])) {
  3477. $fatal = array('type' => $error['type'], 'file' => $error['file'], 'line' => $error['line']);
  3478. self::$loggers['emergency']->emergency($error['message'], $fatal);
  3479. }
  3480. if ($this->displayErrors && $exceptionHandler) {
  3481. $this->handleFatalError($exceptionHandler, $error);
  3482. }
  3483. }
  3484. protected function getFatalErrorHandlers()
  3485. {
  3486. return array(new UndefinedFunctionFatalErrorHandler(), new UndefinedMethodFatalErrorHandler(), new ClassNotFoundFatalErrorHandler());
  3487. }
  3488. private function handleFatalError($exceptionHandler, array $error)
  3489. {
  3490. set_error_handler('var_dump', 0);
  3491. ini_set('display_errors', 1);
  3492. $level = isset($this->levels[$error['type']]) ? $this->levels[$error['type']] : $error['type'];
  3493. $message = sprintf('%s: %s in %s line %d', $level, $error['message'], $error['file'], $error['line']);
  3494. if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
  3495. $exception = new OutOfMemoryException($message, 0, $error['type'], $error['file'], $error['line'], 3, false);
  3496. } else {
  3497. $exception = new FatalErrorException($message, 0, $error['type'], $error['file'], $error['line'], 3, true);
  3498. foreach ($this->getFatalErrorHandlers() as $handler) {
  3499. if ($e = $handler->handleError($error, $exception)) {
  3500. $exception = $e;
  3501. break;
  3502. }
  3503. }
  3504. }
  3505. try {
  3506. call_user_func($exceptionHandler, $exception);
  3507. } catch (\Exception $e) {
  3508. throw $exception;
  3509. }
  3510. }
  3511. }
  3512. class ErrorHandlerCanary
  3513. {
  3514. private static $displayErrors = null;
  3515. public function __construct()
  3516. {
  3517. if (null === self::$displayErrors) {
  3518. self::$displayErrors = ini_set('display_errors', 1);
  3519. }
  3520. }
  3521. public function __destruct()
  3522. {
  3523. if (null !== self::$displayErrors) {
  3524. ini_set('display_errors', self::$displayErrors);
  3525. self::$displayErrors = null;
  3526. }
  3527. }
  3528. }
  3529. namespace Symfony\Component\HttpKernel\Debug;
  3530. use Symfony\Component\Debug\ErrorHandler as DebugErrorHandler;
  3531. class ErrorHandler extends DebugErrorHandler
  3532. {
  3533. }
  3534. namespace Illuminate\Config;
  3535. use Closure;
  3536. use ArrayAccess;
  3537. use Illuminate\Support\NamespacedItemResolver;
  3538. class Repository extends NamespacedItemResolver implements ArrayAccess
  3539. {
  3540. protected $loader;
  3541. protected $environment;
  3542. protected $items = array();
  3543. protected $packages = array();
  3544. protected $afterLoad = array();
  3545. public function __construct(LoaderInterface $loader, $environment)
  3546. {
  3547. $this->loader = $loader;
  3548. $this->environment = $environment;
  3549. }
  3550. public function has($key)
  3551. {
  3552. $default = microtime(true);
  3553. return $this->get($key, $default) !== $default;
  3554. }
  3555. public function hasGroup($key)
  3556. {
  3557. list($namespace, $group, $item) = $this->parseKey($key);
  3558. return $this->loader->exists($group, $namespace);
  3559. }
  3560. public function get($key, $default = null)
  3561. {
  3562. list($namespace, $group, $item) = $this->parseKey($key);
  3563. $collection = $this->getCollection($group, $namespace);
  3564. $this->load($group, $namespace, $collection);
  3565. return array_get($this->items[$collection], $item, $default);
  3566. }
  3567. public function set($key, $value)
  3568. {
  3569. list($namespace, $group, $item) = $this->parseKey($key);
  3570. $collection = $this->getCollection($group, $namespace);
  3571. $this->load($group, $namespace, $collection);
  3572. if (is_null($item)) {
  3573. $this->items[$collection] = $value;
  3574. } else {
  3575. array_set($this->items[$collection], $item, $value);
  3576. }
  3577. }
  3578. protected function load($group, $namespace, $collection)
  3579. {
  3580. $env = $this->environment;
  3581. if (isset($this->items[$collection])) {
  3582. return;
  3583. }
  3584. $items = $this->loader->load($env, $group, $namespace);
  3585. if (isset($this->afterLoad[$namespace])) {
  3586. $items = $this->callAfterLoad($namespace, $group, $items);
  3587. }
  3588. $this->items[$collection] = $items;
  3589. }
  3590. protected function callAfterLoad($namespace, $group, $items)
  3591. {
  3592. $callback = $this->afterLoad[$namespace];
  3593. return call_user_func($callback, $this, $group, $items);
  3594. }
  3595. protected function parseNamespacedSegments($key)
  3596. {
  3597. list($namespace, $item) = explode('::', $key);
  3598. if (in_array($namespace, $this->packages)) {
  3599. return $this->parsePackageSegments($key, $namespace, $item);
  3600. }
  3601. return parent::parseNamespacedSegments($key);
  3602. }
  3603. protected function parsePackageSegments($key, $namespace, $item)
  3604. {
  3605. $itemSegments = explode('.', $item);
  3606. if (!$this->loader->exists($itemSegments[0], $namespace)) {
  3607. return array($namespace, 'config', $item);
  3608. }
  3609. return parent::parseNamespacedSegments($key);
  3610. }
  3611. public function package($package, $hint, $namespace = null)
  3612. {
  3613. $namespace = $this->getPackageNamespace($package, $namespace);
  3614. $this->packages[] = $namespace;
  3615. $this->addNamespace($namespace, $hint);
  3616. $this->afterLoading($namespace, function ($me, $group, $items) use($package) {
  3617. $env = $me->getEnvironment();
  3618. $loader = $me->getLoader();
  3619. return $loader->cascadePackage($env, $package, $group, $items);
  3620. });
  3621. }
  3622. protected function getPackageNamespace($package, $namespace)
  3623. {
  3624. if (is_null($namespace)) {
  3625. list($vendor, $namespace) = explode('/', $package);
  3626. }
  3627. return $namespace;
  3628. }
  3629. public function afterLoading($namespace, Closure $callback)
  3630. {
  3631. $this->afterLoad[$namespace] = $callback;
  3632. }
  3633. protected function getCollection($group, $namespace = null)
  3634. {
  3635. $namespace = $namespace ?: '*';
  3636. return $namespace . '::' . $group;
  3637. }
  3638. public function addNamespace($namespace, $hint)
  3639. {
  3640. $this->loader->addNamespace($namespace, $hint);
  3641. }
  3642. public function getNamespaces()
  3643. {
  3644. return $this->loader->getNamespaces();
  3645. }
  3646. public function getLoader()
  3647. {
  3648. return $this->loader;
  3649. }
  3650. public function setLoader(LoaderInterface $loader)
  3651. {
  3652. $this->loader = $loader;
  3653. }
  3654. public function getEnvironment()
  3655. {
  3656. return $this->environment;
  3657. }
  3658. public function getAfterLoadCallbacks()
  3659. {
  3660. return $this->afterLoad;
  3661. }
  3662. public function getItems()
  3663. {
  3664. return $this->items;
  3665. }
  3666. public function offsetExists($key)
  3667. {
  3668. return $this->has($key);
  3669. }
  3670. public function offsetGet($key)
  3671. {
  3672. return $this->get($key);
  3673. }
  3674. public function offsetSet($key, $value)
  3675. {
  3676. $this->set($key, $value);
  3677. }
  3678. public function offsetUnset($key)
  3679. {
  3680. $this->set($key, null);
  3681. }
  3682. }
  3683. namespace Illuminate\Support;
  3684. class NamespacedItemResolver
  3685. {
  3686. protected $parsed = array();
  3687. public function parseKey($key)
  3688. {
  3689. if (isset($this->parsed[$key])) {
  3690. return $this->parsed[$key];
  3691. }
  3692. $segments = explode('.', $key);
  3693. if (strpos($key, '::') === false) {
  3694. $parsed = $this->parseBasicSegments($segments);
  3695. } else {
  3696. $parsed = $this->parseNamespacedSegments($key);
  3697. }
  3698. return $this->parsed[$key] = $parsed;
  3699. }
  3700. protected function parseBasicSegments(array $segments)
  3701. {
  3702. $group = $segments[0];
  3703. if (count($segments) == 1) {
  3704. return array(null, $group, null);
  3705. } else {
  3706. $item = implode('.', array_slice($segments, 1));
  3707. return array(null, $group, $item);
  3708. }
  3709. }
  3710. protected function parseNamespacedSegments($key)
  3711. {
  3712. list($namespace, $item) = explode('::', $key);
  3713. $itemSegments = explode('.', $item);
  3714. $groupAndItem = array_slice($this->parseBasicSegments($itemSegments), 1);
  3715. return array_merge(array($namespace), $groupAndItem);
  3716. }
  3717. public function setParsedKey($key, $parsed)
  3718. {
  3719. $this->parsed[$key] = $parsed;
  3720. }
  3721. }
  3722. namespace Illuminate\Config;
  3723. use Illuminate\Filesystem\Filesystem;
  3724. class FileLoader implements LoaderInterface
  3725. {
  3726. protected $files;
  3727. protected $defaultPath;
  3728. protected $hints = array();
  3729. protected $exists = array();
  3730. public function __construct(Filesystem $files, $defaultPath)
  3731. {
  3732. $this->files = $files;
  3733. $this->defaultPath = $defaultPath;
  3734. }
  3735. public function load($environment, $group, $namespace = null)
  3736. {
  3737. $items = array();
  3738. $path = $this->getPath($namespace);
  3739. if (is_null($path)) {
  3740. return $items;
  3741. }
  3742. $file = "{$path}/{$group}.php";
  3743. if ($this->files->exists($file)) {
  3744. $items = $this->files->getRequire($file);
  3745. }
  3746. $file = "{$path}/{$environment}/{$group}.php";
  3747. if ($this->files->exists($file)) {
  3748. $items = $this->mergeEnvironment($items, $file);
  3749. }
  3750. return $items;
  3751. }
  3752. protected function mergeEnvironment(array $items, $file)
  3753. {
  3754. return array_replace_recursive($items, $this->files->getRequire($file));
  3755. }
  3756. public function exists($group, $namespace = null)
  3757. {
  3758. $key = $group . $namespace;
  3759. if (isset($this->exists[$key])) {
  3760. return $this->exists[$key];
  3761. }
  3762. $path = $this->getPath($namespace);
  3763. if (is_null($path)) {
  3764. return $this->exists[$key] = false;
  3765. }
  3766. $file = "{$path}/{$group}.php";
  3767. $exists = $this->files->exists($file);
  3768. return $this->exists[$key] = $exists;
  3769. }
  3770. public function cascadePackage($env, $package, $group, $items)
  3771. {
  3772. $file = "packages/{$package}/{$group}.php";
  3773. if ($this->files->exists($path = $this->defaultPath . '/' . $file)) {
  3774. $items = array_merge($items, $this->getRequire($path));
  3775. }
  3776. $path = $this->getPackagePath($env, $package, $group);
  3777. if ($this->files->exists($path)) {
  3778. $items = array_merge($items, $this->getRequire($path));
  3779. }
  3780. return $items;
  3781. }
  3782. protected function getPackagePath($env, $package, $group)
  3783. {
  3784. $file = "packages/{$package}/{$env}/{$group}.php";
  3785. return $this->defaultPath . '/' . $file;
  3786. }
  3787. protected function getPath($namespace)
  3788. {
  3789. if (is_null($namespace)) {
  3790. return $this->defaultPath;
  3791. } elseif (isset($this->hints[$namespace])) {
  3792. return $this->hints[$namespace];
  3793. }
  3794. }
  3795. public function addNamespace($namespace, $hint)
  3796. {
  3797. $this->hints[$namespace] = $hint;
  3798. }
  3799. public function getNamespaces()
  3800. {
  3801. return $this->hints;
  3802. }
  3803. protected function getRequire($path)
  3804. {
  3805. return $this->files->getRequire($path);
  3806. }
  3807. public function getFilesystem()
  3808. {
  3809. return $this->files;
  3810. }
  3811. }
  3812. namespace Illuminate\Config;
  3813. interface LoaderInterface
  3814. {
  3815. public function load($environment, $group, $namespace = null);
  3816. public function exists($group, $namespace = null);
  3817. public function addNamespace($namespace, $hint);
  3818. public function getNamespaces();
  3819. public function cascadePackage($environment, $package, $group, $items);
  3820. }
  3821. namespace Illuminate\Config;
  3822. interface EnvironmentVariablesLoaderInterface
  3823. {
  3824. public function load($environment = null);
  3825. }
  3826. namespace Illuminate\Config;
  3827. use Illuminate\Filesystem\Filesystem;
  3828. class FileEnvironmentVariablesLoader implements EnvironmentVariablesLoaderInterface
  3829. {
  3830. protected $files;
  3831. protected $path;
  3832. public function __construct(Filesystem $files, $path = null)
  3833. {
  3834. $this->files = $files;
  3835. $this->path = $path ?: base_path();
  3836. }
  3837. public function load($environment = null)
  3838. {
  3839. if ($environment == 'production') {
  3840. $environment = null;
  3841. }
  3842. if (!$this->files->exists($path = $this->getFile($environment))) {
  3843. return array();
  3844. } else {
  3845. return array_dot($this->files->getRequire($path));
  3846. }
  3847. }
  3848. protected function getFile($environment)
  3849. {
  3850. if ($environment) {
  3851. return $this->path . '/.env.' . $environment . '.php';
  3852. } else {
  3853. return $this->path . '/.env.php';
  3854. }
  3855. }
  3856. }
  3857. namespace Illuminate\Config;
  3858. class EnvironmentVariables
  3859. {
  3860. protected $loader;
  3861. public function __construct(EnvironmentVariablesLoaderInterface $loader)
  3862. {
  3863. $this->loader = $loader;
  3864. }
  3865. public function load($environment = null)
  3866. {
  3867. foreach ($this->loader->load($environment) as $key => $value) {
  3868. $_ENV[$key] = $value;
  3869. $_SERVER[$key] = $value;
  3870. putenv("{$key}={$value}");
  3871. }
  3872. }
  3873. }
  3874. namespace Illuminate\Filesystem;
  3875. use FilesystemIterator;
  3876. use Symfony\Component\Finder\Finder;
  3877. class FileNotFoundException extends \Exception
  3878. {
  3879. }
  3880. class Filesystem
  3881. {
  3882. public function exists($path)
  3883. {
  3884. return file_exists($path);
  3885. }
  3886. public function get($path)
  3887. {
  3888. if ($this->isFile($path)) {
  3889. return file_get_contents($path);
  3890. }
  3891. throw new FileNotFoundException("File does not exist at path {$path}");
  3892. }
  3893. public function getRequire($path)
  3894. {
  3895. if ($this->isFile($path)) {
  3896. return require $path;
  3897. }
  3898. throw new FileNotFoundException("File does not exist at path {$path}");
  3899. }
  3900. public function requireOnce($file)
  3901. {
  3902. require_once $file;
  3903. }
  3904. public function put($path, $contents)
  3905. {
  3906. return file_put_contents($path, $contents);
  3907. }
  3908. public function prepend($path, $data)
  3909. {
  3910. if ($this->exists($path)) {
  3911. return $this->put($path, $data . $this->get($path));
  3912. } else {
  3913. return $this->put($path, $data);
  3914. }
  3915. }
  3916. public function append($path, $data)
  3917. {
  3918. return file_put_contents($path, $data, FILE_APPEND);
  3919. }
  3920. public function delete($paths)
  3921. {
  3922. $paths = is_array($paths) ? $paths : func_get_args();
  3923. $success = true;
  3924. foreach ($paths as $path) {
  3925. if (!@unlink($path)) {
  3926. $success = false;
  3927. }
  3928. }
  3929. return $success;
  3930. }
  3931. public function move($path, $target)
  3932. {
  3933. return rename($path, $target);
  3934. }
  3935. public function copy($path, $target)
  3936. {
  3937. return copy($path, $target);
  3938. }
  3939. public function extension($path)
  3940. {
  3941. return pathinfo($path, PATHINFO_EXTENSION);
  3942. }
  3943. public function type($path)
  3944. {
  3945. return filetype($path);
  3946. }
  3947. public function size($path)
  3948. {
  3949. return filesize($path);
  3950. }
  3951. public function lastModified($path)
  3952. {
  3953. return filemtime($path);
  3954. }
  3955. public function isDirectory($directory)
  3956. {
  3957. return is_dir($directory);
  3958. }
  3959. public function isWritable($path)
  3960. {
  3961. return is_writable($path);
  3962. }
  3963. public function isFile($file)
  3964. {
  3965. return is_file($file);
  3966. }
  3967. public function glob($pattern, $flags = 0)
  3968. {
  3969. return glob($pattern, $flags);
  3970. }
  3971. public function files($directory)
  3972. {
  3973. $glob = glob($directory . '/*');
  3974. if ($glob === false) {
  3975. return array();
  3976. }
  3977. return array_filter($glob, function ($file) {
  3978. return filetype($file) == 'file';
  3979. });
  3980. }
  3981. public function allFiles($directory)
  3982. {
  3983. return iterator_to_array(Finder::create()->files()->in($directory), false);
  3984. }
  3985. public function directories($directory)
  3986. {
  3987. $directories = array();
  3988. foreach (Finder::create()->in($directory)->directories()->depth(0) as $dir) {
  3989. $directories[] = $dir->getPathname();
  3990. }
  3991. return $directories;
  3992. }
  3993. public function makeDirectory($path, $mode = 493, $recursive = false, $force = false)
  3994. {
  3995. if ($force) {
  3996. return @mkdir($path, $mode, $recursive);
  3997. } else {
  3998. return mkdir($path, $mode, $recursive);
  3999. }
  4000. }
  4001. public function copyDirectory($directory, $destination, $options = null)
  4002. {
  4003. if (!$this->isDirectory($directory)) {
  4004. return false;
  4005. }
  4006. $options = $options ?: FilesystemIterator::SKIP_DOTS;
  4007. if (!$this->isDirectory($destination)) {
  4008. $this->makeDirectory($destination, 511, true);
  4009. }
  4010. $items = new FilesystemIterator($directory, $options);
  4011. foreach ($items as $item) {
  4012. $target = $destination . '/' . $item->getBasename();
  4013. if ($item->isDir()) {
  4014. $path = $item->getPathname();
  4015. if (!$this->copyDirectory($path, $target, $options)) {
  4016. return false;
  4017. }
  4018. } else {
  4019. if (!$this->copy($item->getPathname(), $target)) {
  4020. return false;
  4021. }
  4022. }
  4023. }
  4024. return true;
  4025. }
  4026. public function deleteDirectory($directory, $preserve = false)
  4027. {
  4028. if (!$this->isDirectory($directory)) {
  4029. return false;
  4030. }
  4031. $items = new FilesystemIterator($directory);
  4032. foreach ($items as $item) {
  4033. if ($item->isDir()) {
  4034. $this->deleteDirectory($item->getPathname());
  4035. } else {
  4036. $this->delete($item->getPathname());
  4037. }
  4038. }
  4039. if (!$preserve) {
  4040. @rmdir($directory);
  4041. }
  4042. return true;
  4043. }
  4044. public function cleanDirectory($directory)
  4045. {
  4046. return $this->deleteDirectory($directory, true);
  4047. }
  4048. }
  4049. namespace Illuminate\Foundation;
  4050. class AliasLoader
  4051. {
  4052. protected $aliases;
  4053. protected $registered = false;
  4054. protected static $instance;
  4055. public function __construct(array $aliases = array())
  4056. {
  4057. $this->aliases = $aliases;
  4058. }
  4059. public static function getInstance(array $aliases = array())
  4060. {
  4061. if (is_null(static::$instance)) {
  4062. static::$instance = new static($aliases);
  4063. }
  4064. $aliases = array_merge(static::$instance->getAliases(), $aliases);
  4065. static::$instance->setAliases($aliases);
  4066. return static::$instance;
  4067. }
  4068. public function load($alias)
  4069. {
  4070. if (isset($this->aliases[$alias])) {
  4071. return class_alias($this->aliases[$alias], $alias);
  4072. }
  4073. }
  4074. public function alias($class, $alias)
  4075. {
  4076. $this->aliases[$class] = $alias;
  4077. }
  4078. public function register()
  4079. {
  4080. if (!$this->registered) {
  4081. $this->prependToLoaderStack();
  4082. $this->registered = true;
  4083. }
  4084. }
  4085. protected function prependToLoaderStack()
  4086. {
  4087. spl_autoload_register(array($this, 'load'), true, true);
  4088. }
  4089. public function getAliases()
  4090. {
  4091. return $this->aliases;
  4092. }
  4093. public function setAliases(array $aliases)
  4094. {
  4095. $this->aliases = $aliases;
  4096. }
  4097. public function isRegistered()
  4098. {
  4099. return $this->registered;
  4100. }
  4101. public function setRegistered($value)
  4102. {
  4103. $this->registered = $value;
  4104. }
  4105. public static function setInstance($loader)
  4106. {
  4107. static::$instance = $loader;
  4108. }
  4109. }
  4110. namespace Illuminate\Foundation;
  4111. use Illuminate\Filesystem\Filesystem;
  4112. class ProviderRepository
  4113. {
  4114. protected $files;
  4115. protected $manifestPath;
  4116. protected $default = array('when' => array());
  4117. public function __construct(Filesystem $files, $manifestPath)
  4118. {
  4119. $this->files = $files;
  4120. $this->manifestPath = $manifestPath;
  4121. }
  4122. public function load(Application $app, array $providers)
  4123. {
  4124. $manifest = $this->loadManifest();
  4125. if ($this->shouldRecompile($manifest, $providers)) {
  4126. $manifest = $this->compileManifest($app, $providers);
  4127. }
  4128. if ($app->runningInConsole()) {
  4129. $manifest['eager'] = $manifest['providers'];
  4130. }
  4131. foreach ($manifest['when'] as $provider => $events) {
  4132. $this->registerLoadEvents($app, $provider, $events);
  4133. }
  4134. foreach ($manifest['eager'] as $provider) {
  4135. $app->register($this->createProvider($app, $provider));
  4136. }
  4137. $app->setDeferredServices($manifest['deferred']);
  4138. }
  4139. protected function registerLoadEvents(Application $app, $provider, array $events)
  4140. {
  4141. if (count($events) < 1) {
  4142. return;
  4143. }
  4144. $app->make('events')->listen($events, function () use($app, $provider) {
  4145. $app->register($provider);
  4146. });
  4147. }
  4148. protected function compileManifest(Application $app, $providers)
  4149. {
  4150. $manifest = $this->freshManifest($providers);
  4151. foreach ($providers as $provider) {
  4152. $instance = $this->createProvider($app, $provider);
  4153. if ($instance->isDeferred()) {
  4154. foreach ($instance->provides() as $service) {
  4155. $manifest['deferred'][$service] = $provider;
  4156. }
  4157. $manifest['when'][$provider] = $instance->when();
  4158. } else {
  4159. $manifest['eager'][] = $provider;
  4160. }
  4161. }
  4162. return $this->writeManifest($manifest);
  4163. }
  4164. public function createProvider(Application $app, $provider)
  4165. {
  4166. return new $provider($app);
  4167. }
  4168. public function shouldRecompile($manifest, $providers)
  4169. {
  4170. return is_null($manifest) || $manifest['providers'] != $providers;
  4171. }
  4172. public function loadManifest()
  4173. {
  4174. $path = $this->manifestPath . '/services.json';
  4175. if ($this->files->exists($path)) {
  4176. $manifest = json_decode($this->files->get($path), true);
  4177. return array_merge($this->default, $manifest);
  4178. }
  4179. }
  4180. public function writeManifest($manifest)
  4181. {
  4182. $path = $this->manifestPath . '/services.json';
  4183. $this->files->put($path, json_encode($manifest, JSON_PRETTY_PRINT));
  4184. return $manifest;
  4185. }
  4186. protected function freshManifest(array $providers)
  4187. {
  4188. list($eager, $deferred) = array(array(), array());
  4189. return compact('providers', 'eager', 'deferred');
  4190. }
  4191. public function getFilesystem()
  4192. {
  4193. return $this->files;
  4194. }
  4195. }
  4196. namespace Illuminate\Cookie;
  4197. use Illuminate\Support\ServiceProvider;
  4198. class CookieServiceProvider extends ServiceProvider
  4199. {
  4200. public function register()
  4201. {
  4202. $this->app->bindShared('cookie', function ($app) {
  4203. $config = $app['config']['session'];
  4204. return with(new CookieJar())->setDefaultPathAndDomain($config['path'], $config['domain']);
  4205. });
  4206. }
  4207. }
  4208. namespace Illuminate\Database;
  4209. use Illuminate\Database\Eloquent\Model;
  4210. use Illuminate\Support\ServiceProvider;
  4211. use Illuminate\Database\Connectors\ConnectionFactory;
  4212. class DatabaseServiceProvider extends ServiceProvider
  4213. {
  4214. public function boot()
  4215. {
  4216. Model::setConnectionResolver($this->app['db']);
  4217. Model::setEventDispatcher($this->app['events']);
  4218. }
  4219. public function register()
  4220. {
  4221. $this->app->bindShared('db.factory', function ($app) {
  4222. return new ConnectionFactory($app);
  4223. });
  4224. $this->app->bindShared('db', function ($app) {
  4225. return new DatabaseManager($app, $app['db.factory']);
  4226. });
  4227. }
  4228. }
  4229. namespace Illuminate\Encryption;
  4230. use Illuminate\Support\ServiceProvider;
  4231. class EncryptionServiceProvider extends ServiceProvider
  4232. {
  4233. public function register()
  4234. {
  4235. $this->app->bindShared('encrypter', function ($app) {
  4236. $encrypter = new Encrypter($app['config']['app.key']);
  4237. if ($app['config']->has('app.cipher')) {
  4238. $encrypter->setCipher($app['config']['app.cipher']);
  4239. }
  4240. return $encrypter;
  4241. });
  4242. }
  4243. }
  4244. namespace Illuminate\Filesystem;
  4245. use Illuminate\Support\ServiceProvider;
  4246. class FilesystemServiceProvider extends ServiceProvider
  4247. {
  4248. public function register()
  4249. {
  4250. $this->app->bindShared('files', function () {
  4251. return new Filesystem();
  4252. });
  4253. }
  4254. }
  4255. namespace Illuminate\Session;
  4256. use Illuminate\Support\ServiceProvider;
  4257. class SessionServiceProvider extends ServiceProvider
  4258. {
  4259. public function register()
  4260. {
  4261. $this->setupDefaultDriver();
  4262. $this->registerSessionManager();
  4263. $this->registerSessionDriver();
  4264. }
  4265. protected function setupDefaultDriver()
  4266. {
  4267. if ($this->app->runningInConsole()) {
  4268. $this->app['config']['session.driver'] = 'array';
  4269. }
  4270. }
  4271. protected function registerSessionManager()
  4272. {
  4273. $this->app->bindShared('session', function ($app) {
  4274. return new SessionManager($app);
  4275. });
  4276. }
  4277. protected function registerSessionDriver()
  4278. {
  4279. $this->app->bindShared('session.store', function ($app) {
  4280. $manager = $app['session'];
  4281. return $manager->driver();
  4282. });
  4283. }
  4284. protected function getDriver()
  4285. {
  4286. return $this->app['config']['session.driver'];
  4287. }
  4288. }
  4289. namespace Illuminate\View;
  4290. use Illuminate\Support\ViewErrorBag;
  4291. use Illuminate\View\Engines\PhpEngine;
  4292. use Illuminate\Support\ServiceProvider;
  4293. use Illuminate\View\Engines\CompilerEngine;
  4294. use Illuminate\View\Engines\EngineResolver;
  4295. use Illuminate\View\Compilers\BladeCompiler;
  4296. class ViewServiceProvider extends ServiceProvider
  4297. {
  4298. public function register()
  4299. {
  4300. $this->registerEngineResolver();
  4301. $this->registerViewFinder();
  4302. $this->registerFactory();
  4303. $this->registerSessionBinder();
  4304. }
  4305. public function registerEngineResolver()
  4306. {
  4307. $this->app->bindShared('view.engine.resolver', function ($app) {
  4308. $resolver = new EngineResolver();
  4309. foreach (array('php', 'blade') as $engine) {
  4310. $this->{'register' . ucfirst($engine) . 'Engine'}($resolver);
  4311. }
  4312. return $resolver;
  4313. });
  4314. }
  4315. public function registerPhpEngine($resolver)
  4316. {
  4317. $resolver->register('php', function () {
  4318. return new PhpEngine();
  4319. });
  4320. }
  4321. public function registerBladeEngine($resolver)
  4322. {
  4323. $app = $this->app;
  4324. $app->bindShared('blade.compiler', function ($app) {
  4325. $cache = $app['path.storage'] . '/views';
  4326. return new BladeCompiler($app['files'], $cache);
  4327. });
  4328. $resolver->register('blade', function () use($app) {
  4329. return new CompilerEngine($app['blade.compiler'], $app['files']);
  4330. });
  4331. }
  4332. public function registerViewFinder()
  4333. {
  4334. $this->app->bindShared('view.finder', function ($app) {
  4335. $paths = $app['config']['view.paths'];
  4336. return new FileViewFinder($app['files'], $paths);
  4337. });
  4338. }
  4339. public function registerFactory()
  4340. {
  4341. $this->app->bindShared('view', function ($app) {
  4342. $resolver = $app['view.engine.resolver'];
  4343. $finder = $app['view.finder'];
  4344. $env = new Factory($resolver, $finder, $app['events']);
  4345. $env->setContainer($app);
  4346. $env->share('app', $app);
  4347. return $env;
  4348. });
  4349. }
  4350. protected function registerSessionBinder()
  4351. {
  4352. list($app, $me) = array($this->app, $this);
  4353. $app->booted(function () use($app, $me) {
  4354. if ($me->sessionHasErrors($app)) {
  4355. $errors = $app['session.store']->get('errors');
  4356. $app['view']->share('errors', $errors);
  4357. } else {
  4358. $app['view']->share('errors', new ViewErrorBag());
  4359. }
  4360. });
  4361. }
  4362. public function sessionHasErrors($app)
  4363. {
  4364. $config = $app['config']['session'];
  4365. if (isset($app['session.store']) && !is_null($config['driver'])) {
  4366. return $app['session.store']->has('errors');
  4367. }
  4368. }
  4369. }
  4370. namespace Illuminate\Routing;
  4371. interface RouteFiltererInterface
  4372. {
  4373. public function filter($name, $callback);
  4374. public function callRouteFilter($filter, $parameters, $route, $request, $response = null);
  4375. }
  4376. namespace Illuminate\Routing;
  4377. use Closure;
  4378. use Illuminate\Http\Request;
  4379. use Illuminate\Http\Response;
  4380. use Illuminate\Events\Dispatcher;
  4381. use Illuminate\Container\Container;
  4382. use Symfony\Component\HttpKernel\HttpKernelInterface;
  4383. use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
  4384. use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
  4385. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  4386. class Router implements HttpKernelInterface, RouteFiltererInterface
  4387. {
  4388. protected $events;
  4389. protected $container;
  4390. protected $routes;
  4391. protected $current;
  4392. protected $currentRequest;
  4393. protected $controllerDispatcher;
  4394. protected $inspector;
  4395. protected $filtering = true;
  4396. protected $patternFilters = array();
  4397. protected $regexFilters = array();
  4398. protected $binders = array();
  4399. protected $patterns = array();
  4400. protected $groupStack = array();
  4401. public static $verbs = array('GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS');
  4402. protected $resourceDefaults = array('index', 'create', 'store', 'show', 'edit', 'update', 'destroy');
  4403. public function __construct(Dispatcher $events, Container $container = null)
  4404. {
  4405. $this->events = $events;
  4406. $this->routes = new RouteCollection();
  4407. $this->container = $container ?: new Container();
  4408. $this->bind('_missing', function ($v) {
  4409. return explode('/', $v);
  4410. });
  4411. }
  4412. public function get($uri, $action)
  4413. {
  4414. return $this->addRoute(array('GET', 'HEAD'), $uri, $action);
  4415. }
  4416. public function post($uri, $action)
  4417. {
  4418. return $this->addRoute('POST', $uri, $action);
  4419. }
  4420. public function put($uri, $action)
  4421. {
  4422. return $this->addRoute('PUT', $uri, $action);
  4423. }
  4424. public function patch($uri, $action)
  4425. {
  4426. return $this->addRoute('PATCH', $uri, $action);
  4427. }
  4428. public function delete($uri, $action)
  4429. {
  4430. return $this->addRoute('DELETE', $uri, $action);
  4431. }
  4432. public function options($uri, $action)
  4433. {
  4434. return $this->addRoute('OPTIONS', $uri, $action);
  4435. }
  4436. public function any($uri, $action)
  4437. {
  4438. $verbs = array('GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE');
  4439. return $this->addRoute($verbs, $uri, $action);
  4440. }
  4441. public function match($methods, $uri, $action)
  4442. {
  4443. return $this->addRoute($methods, $uri, $action);
  4444. }
  4445. public function controllers(array $controllers)
  4446. {
  4447. foreach ($controllers as $uri => $name) {
  4448. $this->controller($uri, $name);
  4449. }
  4450. }
  4451. public function controller($uri, $controller, $names = array())
  4452. {
  4453. $prepended = $controller;
  4454. if (count($this->groupStack) > 0) {
  4455. $prepended = $this->prependGroupUses($controller);
  4456. }
  4457. $routable = $this->getInspector()->getRoutable($prepended, $uri);
  4458. foreach ($routable as $method => $routes) {
  4459. foreach ($routes as $route) {
  4460. $this->registerInspected($route, $controller, $method, $names);
  4461. }
  4462. }
  4463. $this->addFallthroughRoute($controller, $uri);
  4464. }
  4465. protected function registerInspected($route, $controller, $method, &$names)
  4466. {
  4467. $action = array('uses' => $controller . '@' . $method);
  4468. $action['as'] = array_pull($names, $method);
  4469. $this->{$route['verb']}($route['uri'], $action);
  4470. }
  4471. protected function addFallthroughRoute($controller, $uri)
  4472. {
  4473. $missing = $this->any($uri . '/{_missing}', $controller . '@missingMethod');
  4474. $missing->where('_missing', '(.*)');
  4475. }
  4476. public function resource($name, $controller, array $options = array())
  4477. {
  4478. if (str_contains($name, '/')) {
  4479. $this->prefixedResource($name, $controller, $options);
  4480. return;
  4481. }
  4482. $base = $this->getResourceWildcard(last(explode('.', $name)));
  4483. $defaults = $this->resourceDefaults;
  4484. foreach ($this->getResourceMethods($defaults, $options) as $m) {
  4485. $this->{'addResource' . ucfirst($m)}($name, $base, $controller, $options);
  4486. }
  4487. }
  4488. protected function prefixedResource($name, $controller, array $options)
  4489. {
  4490. list($name, $prefix) = $this->getResourcePrefix($name);
  4491. $callback = function ($me) use($name, $controller, $options) {
  4492. $me->resource($name, $controller, $options);
  4493. };
  4494. return $this->group(compact('prefix'), $callback);
  4495. }
  4496. protected function getResourcePrefix($name)
  4497. {
  4498. $segments = explode('/', $name);
  4499. $prefix = implode('/', array_slice($segments, 0, -1));
  4500. return array($segments[count($segments) - 1], $prefix);
  4501. }
  4502. protected function getResourceMethods($defaults, $options)
  4503. {
  4504. if (isset($options['only'])) {
  4505. return array_intersect($defaults, (array) $options['only']);
  4506. } elseif (isset($options['except'])) {
  4507. return array_diff($defaults, (array) $options['except']);
  4508. }
  4509. return $defaults;
  4510. }
  4511. public function getResourceUri($resource)
  4512. {
  4513. if (!str_contains($resource, '.')) {
  4514. return $resource;
  4515. }
  4516. $segments = explode('.', $resource);
  4517. $uri = $this->getNestedResourceUri($segments);
  4518. return str_replace('/{' . $this->getResourceWildcard(last($segments)) . '}', '', $uri);
  4519. }
  4520. protected function getNestedResourceUri(array $segments)
  4521. {
  4522. return implode('/', array_map(function ($s) {
  4523. return $s . '/{' . $this->getResourceWildcard($s) . '}';
  4524. }, $segments));
  4525. }
  4526. protected function getResourceAction($resource, $controller, $method, $options)
  4527. {
  4528. $name = $this->getResourceName($resource, $method, $options);
  4529. return array('as' => $name, 'uses' => $controller . '@' . $method);
  4530. }
  4531. protected function getResourceName($resource, $method, $options)
  4532. {
  4533. if (isset($options['names'][$method])) {
  4534. return $options['names'][$method];
  4535. }
  4536. $prefix = isset($options['as']) ? $options['as'] . '.' : '';
  4537. if (count($this->groupStack) == 0) {
  4538. return $prefix . $resource . '.' . $method;
  4539. }
  4540. return $this->getGroupResourceName($prefix, $resource, $method);
  4541. }
  4542. protected function getGroupResourceName($prefix, $resource, $method)
  4543. {
  4544. $group = str_replace('/', '.', $this->getLastGroupPrefix());
  4545. return trim("{$prefix}{$group}.{$resource}.{$method}", '.');
  4546. }
  4547. public function getResourceWildcard($value)
  4548. {
  4549. return str_replace('-', '_', $value);
  4550. }
  4551. protected function addResourceIndex($name, $base, $controller, $options)
  4552. {
  4553. $action = $this->getResourceAction($name, $controller, 'index', $options);
  4554. return $this->get($this->getResourceUri($name), $action);
  4555. }
  4556. protected function addResourceCreate($name, $base, $controller, $options)
  4557. {
  4558. $action = $this->getResourceAction($name, $controller, 'create', $options);
  4559. return $this->get($this->getResourceUri($name) . '/create', $action);
  4560. }
  4561. protected function addResourceStore($name, $base, $controller, $options)
  4562. {
  4563. $action = $this->getResourceAction($name, $controller, 'store', $options);
  4564. return $this->post($this->getResourceUri($name), $action);
  4565. }
  4566. protected function addResourceShow($name, $base, $controller, $options)
  4567. {
  4568. $uri = $this->getResourceUri($name) . '/{' . $base . '}';
  4569. return $this->get($uri, $this->getResourceAction($name, $controller, 'show', $options));
  4570. }
  4571. protected function addResourceEdit($name, $base, $controller, $options)
  4572. {
  4573. $uri = $this->getResourceUri($name) . '/{' . $base . '}/edit';
  4574. return $this->get($uri, $this->getResourceAction($name, $controller, 'edit', $options));
  4575. }
  4576. protected function addResourceUpdate($name, $base, $controller, $options)
  4577. {
  4578. $this->addPutResourceUpdate($name, $base, $controller, $options);
  4579. return $this->addPatchResourceUpdate($name, $base, $controller);
  4580. }
  4581. protected function addPutResourceUpdate($name, $base, $controller, $options)
  4582. {
  4583. $uri = $this->getResourceUri($name) . '/{' . $base . '}';
  4584. return $this->put($uri, $this->getResourceAction($name, $controller, 'update', $options));
  4585. }
  4586. protected function addPatchResourceUpdate($name, $base, $controller)
  4587. {
  4588. $uri = $this->getResourceUri($name) . '/{' . $base . '}';
  4589. $this->patch($uri, $controller . '@update');
  4590. }
  4591. protected function addResourceDestroy($name, $base, $controller, $options)
  4592. {
  4593. $action = $this->getResourceAction($name, $controller, 'destroy', $options);
  4594. return $this->delete($this->getResourceUri($name) . '/{' . $base . '}', $action);
  4595. }
  4596. public function group(array $attributes, Closure $callback)
  4597. {
  4598. $this->updateGroupStack($attributes);
  4599. call_user_func($callback, $this);
  4600. array_pop($this->groupStack);
  4601. }
  4602. protected function updateGroupStack(array $attributes)
  4603. {
  4604. if (count($this->groupStack) > 0) {
  4605. $attributes = $this->mergeGroup($attributes, last($this->groupStack));
  4606. }
  4607. $this->groupStack[] = $attributes;
  4608. }
  4609. public function mergeWithLastGroup($new)
  4610. {
  4611. return $this->mergeGroup($new, last($this->groupStack));
  4612. }
  4613. public static function mergeGroup($new, $old)
  4614. {
  4615. $new['namespace'] = static::formatUsesPrefix($new, $old);
  4616. $new['prefix'] = static::formatGroupPrefix($new, $old);
  4617. if (isset($new['domain'])) {
  4618. unset($old['domain']);
  4619. }
  4620. return array_merge_recursive(array_except($old, array('namespace', 'prefix')), $new);
  4621. }
  4622. protected static function formatUsesPrefix($new, $old)
  4623. {
  4624. if (isset($new['namespace'])) {
  4625. return trim(array_get($old, 'namespace'), '\\') . '\\' . trim($new['namespace'], '\\');
  4626. } else {
  4627. return array_get($old, 'namespace');
  4628. }
  4629. }
  4630. protected static function formatGroupPrefix($new, $old)
  4631. {
  4632. if (isset($new['prefix'])) {
  4633. return trim(array_get($old, 'prefix'), '/') . '/' . trim($new['prefix'], '/');
  4634. } else {
  4635. return array_get($old, 'prefix');
  4636. }
  4637. }
  4638. protected function getLastGroupPrefix()
  4639. {
  4640. if (count($this->groupStack) > 0) {
  4641. return array_get(last($this->groupStack), 'prefix', '');
  4642. }
  4643. return '';
  4644. }
  4645. protected function addRoute($methods, $uri, $action)
  4646. {
  4647. return $this->routes->add($this->createRoute($methods, $uri, $action));
  4648. }
  4649. protected function createRoute($methods, $uri, $action)
  4650. {
  4651. if ($this->routingToController($action)) {
  4652. $action = $this->getControllerAction($action);
  4653. }
  4654. $route = $this->newRoute($methods, $uri = $this->prefix($uri), $action);
  4655. $route->where($this->patterns);
  4656. if (count($this->groupStack) > 0) {
  4657. $this->mergeController($route);
  4658. }
  4659. return $route;
  4660. }
  4661. protected function newRoute($methods, $uri, $action)
  4662. {
  4663. return new Route($methods, $uri, $action);
  4664. }
  4665. protected function prefix($uri)
  4666. {
  4667. return trim(trim($this->getLastGroupPrefix(), '/') . '/' . trim($uri, '/'), '/') ?: '/';
  4668. }
  4669. protected function mergeController($route)
  4670. {
  4671. $action = $this->mergeWithLastGroup($route->getAction());
  4672. $route->setAction($action);
  4673. }
  4674. protected function routingToController($action)
  4675. {
  4676. if ($action instanceof Closure) {
  4677. return false;
  4678. }
  4679. return is_string($action) || is_string(array_get($action, 'uses'));
  4680. }
  4681. protected function getControllerAction($action)
  4682. {
  4683. if (is_string($action)) {
  4684. $action = array('uses' => $action);
  4685. }
  4686. if (count($this->groupStack) > 0) {
  4687. $action['uses'] = $this->prependGroupUses($action['uses']);
  4688. }
  4689. $action['controller'] = $action['uses'];
  4690. $closure = $this->getClassClosure($action['uses']);
  4691. return array_set($action, 'uses', $closure);
  4692. }
  4693. protected function getClassClosure($controller)
  4694. {
  4695. $d = $this->getControllerDispatcher();
  4696. return function () use($d, $controller) {
  4697. $route = $this->current();
  4698. $request = $this->getCurrentRequest();
  4699. list($class, $method) = explode('@', $controller);
  4700. return $d->dispatch($route, $request, $class, $method);
  4701. };
  4702. }
  4703. protected function prependGroupUses($uses)
  4704. {
  4705. $group = last($this->groupStack);
  4706. return isset($group['namespace']) ? $group['namespace'] . '\\' . $uses : $uses;
  4707. }
  4708. public function dispatch(Request $request)
  4709. {
  4710. $this->currentRequest = $request;
  4711. $response = $this->callFilter('before', $request);
  4712. if (is_null($response)) {
  4713. $response = $this->dispatchToRoute($request);
  4714. }
  4715. $response = $this->prepareResponse($request, $response);
  4716. $this->callFilter('after', $request, $response);
  4717. return $response;
  4718. }
  4719. public function dispatchToRoute(Request $request)
  4720. {
  4721. $route = $this->findRoute($request);
  4722. $this->events->fire('router.matched', array($route, $request));
  4723. $response = $this->callRouteBefore($route, $request);
  4724. if (is_null($response)) {
  4725. $response = $route->run($request);
  4726. }
  4727. $response = $this->prepareResponse($request, $response);
  4728. $this->callRouteAfter($route, $request, $response);
  4729. return $response;
  4730. }
  4731. protected function findRoute($request)
  4732. {
  4733. $this->current = $route = $this->routes->match($request);
  4734. return $this->substituteBindings($route);
  4735. }
  4736. protected function substituteBindings($route)
  4737. {
  4738. foreach ($route->parameters() as $key => $value) {
  4739. if (isset($this->binders[$key])) {
  4740. $route->setParameter($key, $this->performBinding($key, $value, $route));
  4741. }
  4742. }
  4743. return $route;
  4744. }
  4745. protected function performBinding($key, $value, $route)
  4746. {
  4747. return call_user_func($this->binders[$key], $value, $route);
  4748. }
  4749. public function matched($callback)
  4750. {
  4751. $this->events->listen('router.matched', $callback);
  4752. }
  4753. public function before($callback)
  4754. {
  4755. $this->addGlobalFilter('before', $callback);
  4756. }
  4757. public function after($callback)
  4758. {
  4759. $this->addGlobalFilter('after', $callback);
  4760. }
  4761. protected function addGlobalFilter($filter, $callback)
  4762. {
  4763. $this->events->listen('router.' . $filter, $this->parseFilter($callback));
  4764. }
  4765. public function filter($name, $callback)
  4766. {
  4767. $this->events->listen('router.filter: ' . $name, $this->parseFilter($callback));
  4768. }
  4769. protected function parseFilter($callback)
  4770. {
  4771. if (is_string($callback) && !str_contains($callback, '@')) {
  4772. return $callback . '@filter';
  4773. } else {
  4774. return $callback;
  4775. }
  4776. }
  4777. public function when($pattern, $name, $methods = null)
  4778. {
  4779. if (!is_null($methods)) {
  4780. $methods = array_map('strtoupper', (array) $methods);
  4781. }
  4782. $this->patternFilters[$pattern][] = compact('name', 'methods');
  4783. }
  4784. public function whenRegex($pattern, $name, $methods = null)
  4785. {
  4786. if (!is_null($methods)) {
  4787. $methods = array_map('strtoupper', (array) $methods);
  4788. }
  4789. $this->regexFilters[$pattern][] = compact('name', 'methods');
  4790. }
  4791. public function model($key, $class, Closure $callback = null)
  4792. {
  4793. return $this->bind($key, function ($value) use($class, $callback) {
  4794. if (is_null($value)) {
  4795. return null;
  4796. }
  4797. if ($model = with(new $class())->find($value)) {
  4798. return $model;
  4799. }
  4800. if ($callback instanceof Closure) {
  4801. return call_user_func($callback);
  4802. }
  4803. throw new NotFoundHttpException();
  4804. });
  4805. }
  4806. public function bind($key, $binder)
  4807. {
  4808. $this->binders[str_replace('-', '_', $key)] = $binder;
  4809. }
  4810. public function pattern($key, $pattern)
  4811. {
  4812. $this->patterns[$key] = $pattern;
  4813. }
  4814. protected function callFilter($filter, $request, $response = null)
  4815. {
  4816. if (!$this->filtering) {
  4817. return null;
  4818. }
  4819. return $this->events->until('router.' . $filter, array($request, $response));
  4820. }
  4821. public function callRouteBefore($route, $request)
  4822. {
  4823. $response = $this->callPatternFilters($route, $request);
  4824. return $response ?: $this->callAttachedBefores($route, $request);
  4825. }
  4826. protected function callPatternFilters($route, $request)
  4827. {
  4828. foreach ($this->findPatternFilters($request) as $filter => $parameters) {
  4829. $response = $this->callRouteFilter($filter, $parameters, $route, $request);
  4830. if (!is_null($response)) {
  4831. return $response;
  4832. }
  4833. }
  4834. }
  4835. public function findPatternFilters($request)
  4836. {
  4837. $results = array();
  4838. list($path, $method) = array($request->path(), $request->getMethod());
  4839. foreach ($this->patternFilters as $pattern => $filters) {
  4840. if (str_is($pattern, $path)) {
  4841. $merge = $this->patternsByMethod($method, $filters);
  4842. $results = array_merge($results, $merge);
  4843. }
  4844. }
  4845. foreach ($this->regexFilters as $pattern => $filters) {
  4846. if (preg_match($pattern, $path)) {
  4847. $merge = $this->patternsByMethod($method, $filters);
  4848. $results = array_merge($results, $merge);
  4849. }
  4850. }
  4851. return $results;
  4852. }
  4853. protected function patternsByMethod($method, $filters)
  4854. {
  4855. $results = array();
  4856. foreach ($filters as $filter) {
  4857. if ($this->filterSupportsMethod($filter, $method)) {
  4858. $parsed = Route::parseFilters($filter['name']);
  4859. $results = array_merge($results, $parsed);
  4860. }
  4861. }
  4862. return $results;
  4863. }
  4864. protected function filterSupportsMethod($filter, $method)
  4865. {
  4866. $methods = $filter['methods'];
  4867. return is_null($methods) || in_array($method, $methods);
  4868. }
  4869. protected function callAttachedBefores($route, $request)
  4870. {
  4871. foreach ($route->beforeFilters() as $filter => $parameters) {
  4872. $response = $this->callRouteFilter($filter, $parameters, $route, $request);
  4873. if (!is_null($response)) {
  4874. return $response;
  4875. }
  4876. }
  4877. }
  4878. public function callRouteAfter($route, $request, $response)
  4879. {
  4880. foreach ($route->afterFilters() as $filter => $parameters) {
  4881. $this->callRouteFilter($filter, $parameters, $route, $request, $response);
  4882. }
  4883. }
  4884. public function callRouteFilter($filter, $parameters, $route, $request, $response = null)
  4885. {
  4886. if (!$this->filtering) {
  4887. return null;
  4888. }
  4889. $data = array_merge(array($route, $request, $response), $parameters);
  4890. return $this->events->until('router.filter: ' . $filter, $this->cleanFilterParameters($data));
  4891. }
  4892. protected function cleanFilterParameters(array $parameters)
  4893. {
  4894. return array_filter($parameters, function ($p) {
  4895. return !is_null($p) && $p !== '';
  4896. });
  4897. }
  4898. protected function prepareResponse($request, $response)
  4899. {
  4900. if (!$response instanceof SymfonyResponse) {
  4901. $response = new Response($response);
  4902. }
  4903. return $response->prepare($request);
  4904. }
  4905. public function withoutFilters($callback)
  4906. {
  4907. $this->disableFilters();
  4908. call_user_func($callback);
  4909. $this->enableFilters();
  4910. }
  4911. public function enableFilters()
  4912. {
  4913. $this->filtering = true;
  4914. }
  4915. public function disableFilters()
  4916. {
  4917. $this->filtering = false;
  4918. }
  4919. public function input($key, $default = null)
  4920. {
  4921. return $this->current()->parameter($key, $default);
  4922. }
  4923. public function getCurrentRoute()
  4924. {
  4925. return $this->current();
  4926. }
  4927. public function current()
  4928. {
  4929. return $this->current;
  4930. }
  4931. public function currentRouteName()
  4932. {
  4933. return $this->current() ? $this->current()->getName() : null;
  4934. }
  4935. public function is()
  4936. {
  4937. foreach (func_get_args() as $pattern) {
  4938. if (str_is($pattern, $this->currentRouteName())) {
  4939. return true;
  4940. }
  4941. }
  4942. return false;
  4943. }
  4944. public function currentRouteNamed($name)
  4945. {
  4946. return $this->current() ? $this->current()->getName() == $name : false;
  4947. }
  4948. public function currentRouteAction()
  4949. {
  4950. $action = $this->current()->getAction();
  4951. return isset($action['controller']) ? $action['controller'] : null;
  4952. }
  4953. public function uses()
  4954. {
  4955. foreach (func_get_args() as $pattern) {
  4956. if (str_is($pattern, $this->currentRouteAction())) {
  4957. return true;
  4958. }
  4959. }
  4960. return false;
  4961. }
  4962. public function currentRouteUses($action)
  4963. {
  4964. return $this->currentRouteAction() == $action;
  4965. }
  4966. public function getCurrentRequest()
  4967. {
  4968. return $this->currentRequest;
  4969. }
  4970. public function getRoutes()
  4971. {
  4972. return $this->routes;
  4973. }
  4974. public function getControllerDispatcher()
  4975. {
  4976. if (is_null($this->controllerDispatcher)) {
  4977. $this->controllerDispatcher = new ControllerDispatcher($this, $this->container);
  4978. }
  4979. return $this->controllerDispatcher;
  4980. }
  4981. public function setControllerDispatcher(ControllerDispatcher $dispatcher)
  4982. {
  4983. $this->controllerDispatcher = $dispatcher;
  4984. }
  4985. public function getInspector()
  4986. {
  4987. return $this->inspector ?: ($this->inspector = new ControllerInspector());
  4988. }
  4989. public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  4990. {
  4991. return $this->dispatch(Request::createFromBase($request));
  4992. }
  4993. }
  4994. namespace Illuminate\Routing;
  4995. use Closure;
  4996. use Illuminate\Http\Request;
  4997. use Illuminate\Routing\Matching\UriValidator;
  4998. use Illuminate\Routing\Matching\HostValidator;
  4999. use Illuminate\Routing\Matching\MethodValidator;
  5000. use Illuminate\Routing\Matching\SchemeValidator;
  5001. use Symfony\Component\Routing\Route as SymfonyRoute;
  5002. class Route
  5003. {
  5004. protected $uri;
  5005. protected $methods;
  5006. protected $action;
  5007. protected $defaults = array();
  5008. protected $wheres = array();
  5009. protected $parameters;
  5010. protected $parameterNames;
  5011. protected $compiled;
  5012. protected static $validators;
  5013. public function __construct($methods, $uri, $action)
  5014. {
  5015. $this->uri = $uri;
  5016. $this->methods = (array) $methods;
  5017. $this->action = $this->parseAction($action);
  5018. if (isset($this->action['prefix'])) {
  5019. $this->prefix($this->action['prefix']);
  5020. }
  5021. }
  5022. public function run()
  5023. {
  5024. $parameters = array_filter($this->parameters(), function ($p) {
  5025. return isset($p);
  5026. });
  5027. return call_user_func_array($this->action['uses'], $parameters);
  5028. }
  5029. public function matches(Request $request, $includingMethod = true)
  5030. {
  5031. $this->compileRoute();
  5032. foreach ($this->getValidators() as $validator) {
  5033. if (!$includingMethod && $validator instanceof MethodValidator) {
  5034. continue;
  5035. }
  5036. if (!$validator->matches($this, $request)) {
  5037. return false;
  5038. }
  5039. }
  5040. return true;
  5041. }
  5042. protected function compileRoute()
  5043. {
  5044. $optionals = $this->extractOptionalParameters();
  5045. $uri = preg_replace('/\\{(\\w+?)\\?\\}/', '{$1}', $this->uri);
  5046. $this->compiled = with(new SymfonyRoute($uri, $optionals, $this->wheres, array(), $this->domain() ?: ''))->compile();
  5047. }
  5048. protected function extractOptionalParameters()
  5049. {
  5050. preg_match_all('/\\{(\\w+?)\\?\\}/', $this->uri, $matches);
  5051. $optional = array();
  5052. if (isset($matches[1])) {
  5053. foreach ($matches[1] as $key) {
  5054. $optional[$key] = null;
  5055. }
  5056. }
  5057. return $optional;
  5058. }
  5059. public function beforeFilters()
  5060. {
  5061. if (!isset($this->action['before'])) {
  5062. return array();
  5063. }
  5064. return $this->parseFilters($this->action['before']);
  5065. }
  5066. public function afterFilters()
  5067. {
  5068. if (!isset($this->action['after'])) {
  5069. return array();
  5070. }
  5071. return $this->parseFilters($this->action['after']);
  5072. }
  5073. public static function parseFilters($filters)
  5074. {
  5075. return array_build(static::explodeFilters($filters), function ($key, $value) {
  5076. return Route::parseFilter($value);
  5077. });
  5078. }
  5079. protected static function explodeFilters($filters)
  5080. {
  5081. if (is_array($filters)) {
  5082. return static::explodeArrayFilters($filters);
  5083. }
  5084. return explode('|', $filters);
  5085. }
  5086. protected static function explodeArrayFilters(array $filters)
  5087. {
  5088. $results = array();
  5089. foreach ($filters as $filter) {
  5090. $results = array_merge($results, explode('|', $filter));
  5091. }
  5092. return $results;
  5093. }
  5094. public static function parseFilter($filter)
  5095. {
  5096. if (!str_contains($filter, ':')) {
  5097. return array($filter, array());
  5098. }
  5099. return static::parseParameterFilter($filter);
  5100. }
  5101. protected static function parseParameterFilter($filter)
  5102. {
  5103. list($name, $parameters) = explode(':', $filter, 2);
  5104. return array($name, explode(',', $parameters));
  5105. }
  5106. public function getParameter($name, $default = null)
  5107. {
  5108. return $this->parameter($name, $default);
  5109. }
  5110. public function parameter($name, $default = null)
  5111. {
  5112. return array_get($this->parameters(), $name) ?: $default;
  5113. }
  5114. public function setParameter($name, $value)
  5115. {
  5116. $this->parameters();
  5117. $this->parameters[$name] = $value;
  5118. }
  5119. public function forgetParameter($name)
  5120. {
  5121. $this->parameters();
  5122. unset($this->parameters[$name]);
  5123. }
  5124. public function parameters()
  5125. {
  5126. if (isset($this->parameters)) {
  5127. return array_map(function ($value) {
  5128. return is_string($value) ? rawurldecode($value) : $value;
  5129. }, $this->parameters);
  5130. }
  5131. throw new \LogicException('Route is not bound.');
  5132. }
  5133. public function parametersWithoutNulls()
  5134. {
  5135. return array_filter($this->parameters(), function ($p) {
  5136. return !is_null($p);
  5137. });
  5138. }
  5139. public function parameterNames()
  5140. {
  5141. if (isset($this->parameterNames)) {
  5142. return $this->parameterNames;
  5143. }
  5144. return $this->parameterNames = $this->compileParameterNames();
  5145. }
  5146. protected function compileParameterNames()
  5147. {
  5148. preg_match_all('/\\{(.*?)\\}/', $this->domain() . $this->uri, $matches);
  5149. return array_map(function ($m) {
  5150. return trim($m, '?');
  5151. }, $matches[1]);
  5152. }
  5153. public function bind(Request $request)
  5154. {
  5155. $this->compileRoute();
  5156. $this->bindParameters($request);
  5157. return $this;
  5158. }
  5159. public function bindParameters(Request $request)
  5160. {
  5161. $params = $this->matchToKeys(array_slice($this->bindPathParameters($request), 1));
  5162. if (!is_null($this->compiled->getHostRegex())) {
  5163. $params = $this->bindHostParameters($request, $params);
  5164. }
  5165. return $this->parameters = $this->replaceDefaults($params);
  5166. }
  5167. protected function bindPathParameters(Request $request)
  5168. {
  5169. preg_match($this->compiled->getRegex(), '/' . $request->decodedPath(), $matches);
  5170. return $matches;
  5171. }
  5172. protected function bindHostParameters(Request $request, $parameters)
  5173. {
  5174. preg_match($this->compiled->getHostRegex(), $request->getHost(), $matches);
  5175. return array_merge($this->matchToKeys(array_slice($matches, 1)), $parameters);
  5176. }
  5177. protected function matchToKeys(array $matches)
  5178. {
  5179. if (count($this->parameterNames()) == 0) {
  5180. return array();
  5181. }
  5182. $parameters = array_intersect_key($matches, array_flip($this->parameterNames()));
  5183. return array_filter($parameters, function ($value) {
  5184. return is_string($value) && strlen($value) > 0;
  5185. });
  5186. }
  5187. protected function replaceDefaults(array $parameters)
  5188. {
  5189. foreach ($parameters as $key => &$value) {
  5190. $value = isset($value) ? $value : array_get($this->defaults, $key);
  5191. }
  5192. return $parameters;
  5193. }
  5194. protected function parseAction($action)
  5195. {
  5196. if (is_callable($action)) {
  5197. return array('uses' => $action);
  5198. } elseif (!isset($action['uses'])) {
  5199. $action['uses'] = $this->findClosure($action);
  5200. }
  5201. return $action;
  5202. }
  5203. protected function findClosure(array $action)
  5204. {
  5205. return array_first($action, function ($key, $value) {
  5206. return is_callable($value);
  5207. });
  5208. }
  5209. public static function getValidators()
  5210. {
  5211. if (isset(static::$validators)) {
  5212. return static::$validators;
  5213. }
  5214. return static::$validators = array(new MethodValidator(), new SchemeValidator(), new HostValidator(), new UriValidator());
  5215. }
  5216. public function before($filters)
  5217. {
  5218. return $this->addFilters('before', $filters);
  5219. }
  5220. public function after($filters)
  5221. {
  5222. return $this->addFilters('after', $filters);
  5223. }
  5224. protected function addFilters($type, $filters)
  5225. {
  5226. if (isset($this->action[$type])) {
  5227. $this->action[$type] .= '|' . $filters;
  5228. } else {
  5229. $this->action[$type] = $filters;
  5230. }
  5231. return $this;
  5232. }
  5233. public function defaults($key, $value)
  5234. {
  5235. $this->defaults[$key] = $value;
  5236. return $this;
  5237. }
  5238. public function where($name, $expression = null)
  5239. {
  5240. foreach ($this->parseWhere($name, $expression) as $name => $expression) {
  5241. $this->wheres[$name] = $expression;
  5242. }
  5243. return $this;
  5244. }
  5245. protected function parseWhere($name, $expression)
  5246. {
  5247. return is_array($name) ? $name : array($name => $expression);
  5248. }
  5249. protected function whereArray(array $wheres)
  5250. {
  5251. foreach ($wheres as $name => $expression) {
  5252. $this->where($name, $expression);
  5253. }
  5254. return $this;
  5255. }
  5256. public function prefix($prefix)
  5257. {
  5258. $this->uri = trim($prefix, '/') . '/' . trim($this->uri, '/');
  5259. return $this;
  5260. }
  5261. public function getPath()
  5262. {
  5263. return $this->uri();
  5264. }
  5265. public function uri()
  5266. {
  5267. return $this->uri;
  5268. }
  5269. public function getMethods()
  5270. {
  5271. return $this->methods();
  5272. }
  5273. public function methods()
  5274. {
  5275. return $this->methods;
  5276. }
  5277. public function httpOnly()
  5278. {
  5279. return in_array('http', $this->action, true);
  5280. }
  5281. public function httpsOnly()
  5282. {
  5283. return $this->secure();
  5284. }
  5285. public function secure()
  5286. {
  5287. return in_array('https', $this->action, true);
  5288. }
  5289. public function domain()
  5290. {
  5291. return array_get($this->action, 'domain');
  5292. }
  5293. public function getUri()
  5294. {
  5295. return $this->uri;
  5296. }
  5297. public function setUri($uri)
  5298. {
  5299. $this->uri = $uri;
  5300. return $this;
  5301. }
  5302. public function getPrefix()
  5303. {
  5304. return array_get($this->action, 'prefix');
  5305. }
  5306. public function getName()
  5307. {
  5308. return array_get($this->action, 'as');
  5309. }
  5310. public function getActionName()
  5311. {
  5312. return array_get($this->action, 'controller', 'Closure');
  5313. }
  5314. public function getAction()
  5315. {
  5316. return $this->action;
  5317. }
  5318. public function setAction(array $action)
  5319. {
  5320. $this->action = $action;
  5321. return $this;
  5322. }
  5323. public function getCompiled()
  5324. {
  5325. return $this->compiled;
  5326. }
  5327. }
  5328. namespace Illuminate\Routing;
  5329. use Countable;
  5330. use ArrayIterator;
  5331. use IteratorAggregate;
  5332. use Illuminate\Http\Request;
  5333. use Illuminate\Http\Response;
  5334. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  5335. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  5336. class RouteCollection implements Countable, IteratorAggregate
  5337. {
  5338. protected $routes = array();
  5339. protected $allRoutes = array();
  5340. protected $nameList = array();
  5341. protected $actionList = array();
  5342. public function add(Route $route)
  5343. {
  5344. $this->addToCollections($route);
  5345. $this->addLookups($route);
  5346. return $route;
  5347. }
  5348. protected function addToCollections($route)
  5349. {
  5350. foreach ($route->methods() as $method) {
  5351. $this->routes[$method][$route->domain() . $route->getUri()] = $route;
  5352. }
  5353. $this->allRoutes[$method . $route->domain() . $route->getUri()] = $route;
  5354. }
  5355. protected function addLookups($route)
  5356. {
  5357. $action = $route->getAction();
  5358. if (isset($action['as'])) {
  5359. $this->nameList[$action['as']] = $route;
  5360. }
  5361. if (isset($action['controller'])) {
  5362. $this->addToActionList($action, $route);
  5363. }
  5364. }
  5365. protected function addToActionList($action, $route)
  5366. {
  5367. if (!isset($this->actionList[$action['controller']])) {
  5368. $this->actionList[$action['controller']] = $route;
  5369. }
  5370. }
  5371. public function match(Request $request)
  5372. {
  5373. $routes = $this->get($request->getMethod());
  5374. $route = $this->check($routes, $request);
  5375. if (!is_null($route)) {
  5376. return $route->bind($request);
  5377. }
  5378. $others = $this->checkForAlternateVerbs($request);
  5379. if (count($others) > 0) {
  5380. return $this->getOtherMethodsRoute($request, $others);
  5381. }
  5382. throw new NotFoundHttpException();
  5383. }
  5384. protected function checkForAlternateVerbs($request)
  5385. {
  5386. $methods = array_diff(Router::$verbs, array($request->getMethod()));
  5387. $others = array();
  5388. foreach ($methods as $method) {
  5389. if (!is_null($this->check($this->get($method), $request, false))) {
  5390. $others[] = $method;
  5391. }
  5392. }
  5393. return $others;
  5394. }
  5395. protected function getOtherMethodsRoute($request, array $others)
  5396. {
  5397. if ($request->method() == 'OPTIONS') {
  5398. return with(new Route('OPTIONS', $request->path(), function () use($others) {
  5399. return new Response('', 200, array('Allow' => implode(',', $others)));
  5400. }))->bind($request);
  5401. } else {
  5402. $this->methodNotAllowed($others);
  5403. }
  5404. }
  5405. protected function methodNotAllowed(array $others)
  5406. {
  5407. throw new MethodNotAllowedHttpException($others);
  5408. }
  5409. protected function check(array $routes, $request, $includingMethod = true)
  5410. {
  5411. return array_first($routes, function ($key, $value) use($request, $includingMethod) {
  5412. return $value->matches($request, $includingMethod);
  5413. });
  5414. }
  5415. protected function get($method = null)
  5416. {
  5417. if (is_null($method)) {
  5418. return $this->getRoutes();
  5419. }
  5420. return array_get($this->routes, $method, array());
  5421. }
  5422. public function hasNamedRoute($name)
  5423. {
  5424. return !is_null($this->getByName($name));
  5425. }
  5426. public function getByName($name)
  5427. {
  5428. return isset($this->nameList[$name]) ? $this->nameList[$name] : null;
  5429. }
  5430. public function getByAction($action)
  5431. {
  5432. return isset($this->actionList[$action]) ? $this->actionList[$action] : null;
  5433. }
  5434. public function getRoutes()
  5435. {
  5436. return array_values($this->allRoutes);
  5437. }
  5438. public function getIterator()
  5439. {
  5440. return new ArrayIterator($this->getRoutes());
  5441. }
  5442. public function count()
  5443. {
  5444. return count($this->getRoutes());
  5445. }
  5446. }
  5447. namespace Illuminate\Routing;
  5448. use Closure;
  5449. use Illuminate\Http\Request;
  5450. use Illuminate\Container\Container;
  5451. class ControllerDispatcher
  5452. {
  5453. protected $filterer;
  5454. protected $container;
  5455. public function __construct(RouteFiltererInterface $filterer, Container $container = null)
  5456. {
  5457. $this->filterer = $filterer;
  5458. $this->container = $container;
  5459. }
  5460. public function dispatch(Route $route, Request $request, $controller, $method)
  5461. {
  5462. $instance = $this->makeController($controller);
  5463. $this->assignAfter($instance, $route, $request, $method);
  5464. $response = $this->before($instance, $route, $request, $method);
  5465. if (is_null($response)) {
  5466. $response = $this->call($instance, $route, $method);
  5467. }
  5468. return $response;
  5469. }
  5470. protected function makeController($controller)
  5471. {
  5472. Controller::setFilterer($this->filterer);
  5473. return $this->container->make($controller);
  5474. }
  5475. protected function call($instance, $route, $method)
  5476. {
  5477. $parameters = $route->parametersWithoutNulls();
  5478. return $instance->callAction($method, $parameters);
  5479. }
  5480. protected function before($instance, $route, $request, $method)
  5481. {
  5482. foreach ($instance->getBeforeFilters() as $filter) {
  5483. if ($this->filterApplies($filter, $request, $method)) {
  5484. $response = $this->callFilter($filter, $route, $request);
  5485. if (!is_null($response)) {
  5486. return $response;
  5487. }
  5488. }
  5489. }
  5490. }
  5491. protected function assignAfter($instance, $route, $request, $method)
  5492. {
  5493. foreach ($instance->getAfterFilters() as $filter) {
  5494. if ($this->filterApplies($filter, $request, $method)) {
  5495. $route->after($this->getAssignableAfter($filter));
  5496. }
  5497. }
  5498. }
  5499. protected function getAssignableAfter($filter)
  5500. {
  5501. return $filter['original'] instanceof Closure ? $filter['filter'] : $filter['original'];
  5502. }
  5503. protected function filterApplies($filter, $request, $method)
  5504. {
  5505. foreach (array('Only', 'Except', 'On') as $type) {
  5506. if ($this->{"filterFails{$type}"}($filter, $request, $method)) {
  5507. return false;
  5508. }
  5509. }
  5510. return true;
  5511. }
  5512. protected function filterFailsOnly($filter, $request, $method)
  5513. {
  5514. if (!isset($filter['options']['only'])) {
  5515. return false;
  5516. }
  5517. return !in_array($method, (array) $filter['options']['only']);
  5518. }
  5519. protected function filterFailsExcept($filter, $request, $method)
  5520. {
  5521. if (!isset($filter['options']['except'])) {
  5522. return false;
  5523. }
  5524. return in_array($method, (array) $filter['options']['except']);
  5525. }
  5526. protected function filterFailsOn($filter, $request, $method)
  5527. {
  5528. $on = array_get($filter, 'options.on', null);
  5529. if (is_null($on)) {
  5530. return false;
  5531. }
  5532. if (is_string($on)) {
  5533. $on = explode('|', $on);
  5534. }
  5535. return !in_array(strtolower($request->getMethod()), $on);
  5536. }
  5537. protected function callFilter($filter, $route, $request)
  5538. {
  5539. extract($filter);
  5540. return $this->filterer->callRouteFilter($filter, $parameters, $route, $request);
  5541. }
  5542. }
  5543. namespace Illuminate\Routing;
  5544. use Illuminate\Http\Request;
  5545. use InvalidArgumentException;
  5546. class UrlGenerator
  5547. {
  5548. protected $routes;
  5549. protected $request;
  5550. protected $forcedRoot;
  5551. protected $forceSchema;
  5552. protected $dontEncode = array('%2F' => '/', '%40' => '@', '%3A' => ':', '%3B' => ';', '%2C' => ',', '%3D' => '=', '%2B' => '+', '%21' => '!', '%2A' => '*', '%7C' => '|');
  5553. public function __construct(RouteCollection $routes, Request $request)
  5554. {
  5555. $this->routes = $routes;
  5556. $this->setRequest($request);
  5557. }
  5558. public function full()
  5559. {
  5560. return $this->request->fullUrl();
  5561. }
  5562. public function current()
  5563. {
  5564. return $this->to($this->request->getPathInfo());
  5565. }
  5566. public function previous()
  5567. {
  5568. return $this->to($this->request->headers->get('referer'));
  5569. }
  5570. public function to($path, $extra = array(), $secure = null)
  5571. {
  5572. if ($this->isValidUrl($path)) {
  5573. return $path;
  5574. }
  5575. $scheme = $this->getScheme($secure);
  5576. $tail = implode('/', array_map('rawurlencode', (array) $extra));
  5577. $root = $this->getRootUrl($scheme);
  5578. return $this->trimUrl($root, $path, $tail);
  5579. }
  5580. public function secure($path, $parameters = array())
  5581. {
  5582. return $this->to($path, $parameters, true);
  5583. }
  5584. public function asset($path, $secure = null)
  5585. {
  5586. if ($this->isValidUrl($path)) {
  5587. return $path;
  5588. }
  5589. $root = $this->getRootUrl($this->getScheme($secure));
  5590. return $this->removeIndex($root) . '/' . trim($path, '/');
  5591. }
  5592. protected function removeIndex($root)
  5593. {
  5594. $i = 'index.php';
  5595. return str_contains($root, $i) ? str_replace('/' . $i, '', $root) : $root;
  5596. }
  5597. public function secureAsset($path)
  5598. {
  5599. return $this->asset($path, true);
  5600. }
  5601. protected function getScheme($secure)
  5602. {
  5603. if (is_null($secure)) {
  5604. return $this->forceSchema ?: $this->request->getScheme() . '://';
  5605. } else {
  5606. return $secure ? 'https://' : 'http://';
  5607. }
  5608. }
  5609. public function forceSchema($schema)
  5610. {
  5611. $this->forceSchema = $schema . '://';
  5612. }
  5613. public function route($name, $parameters = array(), $absolute = true, $route = null)
  5614. {
  5615. $route = $route ?: $this->routes->getByName($name);
  5616. $parameters = (array) $parameters;
  5617. if (!is_null($route)) {
  5618. return $this->toRoute($route, $parameters, $absolute);
  5619. } else {
  5620. throw new InvalidArgumentException("Route [{$name}] not defined.");
  5621. }
  5622. }
  5623. protected function toRoute($route, array $parameters, $absolute)
  5624. {
  5625. $domain = $this->getRouteDomain($route, $parameters);
  5626. $uri = strtr(rawurlencode($this->trimUrl($root = $this->replaceRoot($route, $domain, $parameters), $this->replaceRouteParameters($route->uri(), $parameters))), $this->dontEncode) . $this->getRouteQueryString($parameters);
  5627. return $absolute ? $uri : '/' . ltrim(str_replace($root, '', $uri), '/');
  5628. }
  5629. protected function replaceRoot($route, $domain, &$parameters)
  5630. {
  5631. return $this->replaceRouteParameters($this->getRouteRoot($route, $domain), $parameters);
  5632. }
  5633. protected function replaceRouteParameters($path, array &$parameters)
  5634. {
  5635. if (count($parameters)) {
  5636. $path = preg_replace_sub('/\\{.*?\\}/', $parameters, $this->replaceNamedParameters($path, $parameters));
  5637. }
  5638. return trim(preg_replace('/\\{.*?\\?\\}/', '', $path), '/');
  5639. }
  5640. protected function replaceNamedParameters($path, &$parameters)
  5641. {
  5642. return preg_replace_callback('/\\{(.*?)\\??\\}/', function ($m) use(&$parameters) {
  5643. return isset($parameters[$m[1]]) ? array_pull($parameters, $m[1]) : $m[0];
  5644. }, $path);
  5645. }
  5646. protected function getRouteQueryString(array $parameters)
  5647. {
  5648. if (count($parameters) == 0) {
  5649. return '';
  5650. }
  5651. $query = http_build_query($keyed = $this->getStringParameters($parameters));
  5652. if (count($keyed) < count($parameters)) {
  5653. $query .= '&' . implode('&', $this->getNumericParameters($parameters));
  5654. }
  5655. return '?' . trim($query, '&');
  5656. }
  5657. protected function getStringParameters(array $parameters)
  5658. {
  5659. return array_where($parameters, function ($k, $v) {
  5660. return is_string($k);
  5661. });
  5662. }
  5663. protected function getNumericParameters(array $parameters)
  5664. {
  5665. return array_where($parameters, function ($k, $v) {
  5666. return is_numeric($k);
  5667. });
  5668. }
  5669. protected function getRouteDomain($route, &$parameters)
  5670. {
  5671. return $route->domain() ? $this->formatDomain($route, $parameters) : null;
  5672. }
  5673. protected function formatDomain($route, &$parameters)
  5674. {
  5675. return $this->addPortToDomain($this->getDomainAndScheme($route));
  5676. }
  5677. protected function getDomainAndScheme($route)
  5678. {
  5679. return $this->getRouteScheme($route) . $route->domain();
  5680. }
  5681. protected function addPortToDomain($domain)
  5682. {
  5683. if (in_array($this->request->getPort(), array('80', '443'))) {
  5684. return $domain;
  5685. } else {
  5686. return $domain .= ':' . $this->request->getPort();
  5687. }
  5688. }
  5689. protected function getRouteRoot($route, $domain)
  5690. {
  5691. return $this->getRootUrl($this->getRouteScheme($route), $domain);
  5692. }
  5693. protected function getRouteScheme($route)
  5694. {
  5695. if ($route->httpOnly()) {
  5696. return $this->getScheme(false);
  5697. } elseif ($route->httpsOnly()) {
  5698. return $this->getScheme(true);
  5699. } else {
  5700. return $this->getScheme(null);
  5701. }
  5702. }
  5703. public function action($action, $parameters = array(), $absolute = true)
  5704. {
  5705. return $this->route($action, $parameters, $absolute, $this->routes->getByAction($action));
  5706. }
  5707. protected function getRootUrl($scheme, $root = null)
  5708. {
  5709. if (is_null($root)) {
  5710. $root = $this->forcedRoot ?: $this->request->root();
  5711. }
  5712. $start = starts_with($root, 'http://') ? 'http://' : 'https://';
  5713. return preg_replace('~' . $start . '~', $scheme, $root, 1);
  5714. }
  5715. public function forceRootUrl($root)
  5716. {
  5717. $this->forcedRoot = $root;
  5718. }
  5719. public function isValidUrl($path)
  5720. {
  5721. if (starts_with($path, array('#', '//', 'mailto:', 'tel:'))) {
  5722. return true;
  5723. }
  5724. return filter_var($path, FILTER_VALIDATE_URL) !== false;
  5725. }
  5726. protected function trimUrl($root, $path, $tail = '')
  5727. {
  5728. return trim($root . '/' . trim($path . '/' . $tail, '/'), '/');
  5729. }
  5730. public function getRequest()
  5731. {
  5732. return $this->request;
  5733. }
  5734. public function setRequest(Request $request)
  5735. {
  5736. $this->request = $request;
  5737. }
  5738. }
  5739. namespace Illuminate\Routing\Matching;
  5740. use Illuminate\Http\Request;
  5741. use Illuminate\Routing\Route;
  5742. interface ValidatorInterface
  5743. {
  5744. public function matches(Route $route, Request $request);
  5745. }
  5746. namespace Illuminate\Routing\Matching;
  5747. use Illuminate\Http\Request;
  5748. use Illuminate\Routing\Route;
  5749. class HostValidator implements ValidatorInterface
  5750. {
  5751. public function matches(Route $route, Request $request)
  5752. {
  5753. if (is_null($route->getCompiled()->getHostRegex())) {
  5754. return true;
  5755. }
  5756. return preg_match($route->getCompiled()->getHostRegex(), $request->getHost());
  5757. }
  5758. }
  5759. namespace Illuminate\Routing\Matching;
  5760. use Illuminate\Http\Request;
  5761. use Illuminate\Routing\Route;
  5762. class MethodValidator implements ValidatorInterface
  5763. {
  5764. public function matches(Route $route, Request $request)
  5765. {
  5766. return in_array($request->getMethod(), $route->methods());
  5767. }
  5768. }
  5769. namespace Illuminate\Routing\Matching;
  5770. use Illuminate\Http\Request;
  5771. use Illuminate\Routing\Route;
  5772. class SchemeValidator implements ValidatorInterface
  5773. {
  5774. public function matches(Route $route, Request $request)
  5775. {
  5776. if ($route->httpOnly()) {
  5777. return !$request->secure();
  5778. } elseif ($route->secure()) {
  5779. return $request->secure();
  5780. }
  5781. return true;
  5782. }
  5783. }
  5784. namespace Illuminate\Routing\Matching;
  5785. use Illuminate\Http\Request;
  5786. use Illuminate\Routing\Route;
  5787. class UriValidator implements ValidatorInterface
  5788. {
  5789. public function matches(Route $route, Request $request)
  5790. {
  5791. $path = $request->path() == '/' ? '/' : '/' . $request->path();
  5792. return preg_match($route->getCompiled()->getRegex(), rawurldecode($path));
  5793. }
  5794. }
  5795. namespace Illuminate\Workbench;
  5796. use Illuminate\Support\ServiceProvider;
  5797. use Illuminate\Workbench\Console\WorkbenchMakeCommand;
  5798. class WorkbenchServiceProvider extends ServiceProvider
  5799. {
  5800. protected $defer = false;
  5801. public function register()
  5802. {
  5803. $this->app->bindShared('package.creator', function ($app) {
  5804. return new PackageCreator($app['files']);
  5805. });
  5806. $this->app->bindShared('command.workbench', function ($app) {
  5807. return new WorkbenchMakeCommand($app['package.creator']);
  5808. });
  5809. $this->commands('command.workbench');
  5810. }
  5811. public function provides()
  5812. {
  5813. return array('package.creator', 'command.workbench');
  5814. }
  5815. }
  5816. namespace Illuminate\Events;
  5817. use Illuminate\Container\Container;
  5818. class Dispatcher
  5819. {
  5820. protected $container;
  5821. protected $listeners = array();
  5822. protected $wildcards = array();
  5823. protected $sorted = array();
  5824. protected $firing = array();
  5825. public function __construct(Container $container = null)
  5826. {
  5827. $this->container = $container ?: new Container();
  5828. }
  5829. public function listen($events, $listener, $priority = 0)
  5830. {
  5831. foreach ((array) $events as $event) {
  5832. if (str_contains($event, '*')) {
  5833. $this->setupWildcardListen($event, $listener);
  5834. } else {
  5835. $this->listeners[$event][$priority][] = $this->makeListener($listener);
  5836. unset($this->sorted[$event]);
  5837. }
  5838. }
  5839. }
  5840. protected function setupWildcardListen($event, $listener)
  5841. {
  5842. $this->wildcards[$event][] = $this->makeListener($listener);
  5843. }
  5844. public function hasListeners($eventName)
  5845. {
  5846. return isset($this->listeners[$eventName]);
  5847. }
  5848. public function queue($event, $payload = array())
  5849. {
  5850. $this->listen($event . '_queue', function () use($event, $payload) {
  5851. $this->fire($event, $payload);
  5852. });
  5853. }
  5854. public function subscribe($subscriber)
  5855. {
  5856. $subscriber = $this->resolveSubscriber($subscriber);
  5857. $subscriber->subscribe($this);
  5858. }
  5859. protected function resolveSubscriber($subscriber)
  5860. {
  5861. if (is_string($subscriber)) {
  5862. return $this->container->make($subscriber);
  5863. }
  5864. return $subscriber;
  5865. }
  5866. public function until($event, $payload = array())
  5867. {
  5868. return $this->fire($event, $payload, true);
  5869. }
  5870. public function flush($event)
  5871. {
  5872. $this->fire($event . '_queue');
  5873. }
  5874. public function firing()
  5875. {
  5876. return last($this->firing);
  5877. }
  5878. public function fire($event, $payload = array(), $halt = false)
  5879. {
  5880. $responses = array();
  5881. if (!is_array($payload)) {
  5882. $payload = array($payload);
  5883. }
  5884. $this->firing[] = $event;
  5885. foreach ($this->getListeners($event) as $listener) {
  5886. $response = call_user_func_array($listener, $payload);
  5887. if (!is_null($response) && $halt) {
  5888. array_pop($this->firing);
  5889. return $response;
  5890. }
  5891. if ($response === false) {
  5892. break;
  5893. }
  5894. $responses[] = $response;
  5895. }
  5896. array_pop($this->firing);
  5897. return $halt ? null : $responses;
  5898. }
  5899. public function getListeners($eventName)
  5900. {
  5901. $wildcards = $this->getWildcardListeners($eventName);
  5902. if (!isset($this->sorted[$eventName])) {
  5903. $this->sortListeners($eventName);
  5904. }
  5905. return array_merge($this->sorted[$eventName], $wildcards);
  5906. }
  5907. protected function getWildcardListeners($eventName)
  5908. {
  5909. $wildcards = array();
  5910. foreach ($this->wildcards as $key => $listeners) {
  5911. if (str_is($key, $eventName)) {
  5912. $wildcards = array_merge($wildcards, $listeners);
  5913. }
  5914. }
  5915. return $wildcards;
  5916. }
  5917. protected function sortListeners($eventName)
  5918. {
  5919. $this->sorted[$eventName] = array();
  5920. if (isset($this->listeners[$eventName])) {
  5921. krsort($this->listeners[$eventName]);
  5922. $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
  5923. }
  5924. }
  5925. public function makeListener($listener)
  5926. {
  5927. if (is_string($listener)) {
  5928. $listener = $this->createClassListener($listener);
  5929. }
  5930. return $listener;
  5931. }
  5932. public function createClassListener($listener)
  5933. {
  5934. $container = $this->container;
  5935. return function () use($listener, $container) {
  5936. $segments = explode('@', $listener);
  5937. $method = count($segments) == 2 ? $segments[1] : 'handle';
  5938. $callable = array($container->make($segments[0]), $method);
  5939. $data = func_get_args();
  5940. return call_user_func_array($callable, $data);
  5941. };
  5942. }
  5943. public function forget($event)
  5944. {
  5945. unset($this->listeners[$event]);
  5946. unset($this->sorted[$event]);
  5947. }
  5948. }
  5949. namespace Illuminate\Database\Eloquent;
  5950. use DateTime;
  5951. use ArrayAccess;
  5952. use Carbon\Carbon;
  5953. use LogicException;
  5954. use JsonSerializable;
  5955. use Illuminate\Events\Dispatcher;
  5956. use Illuminate\Database\Eloquent\Relations\Pivot;
  5957. use Illuminate\Database\Eloquent\Relations\HasOne;
  5958. use Illuminate\Database\Eloquent\Relations\HasMany;
  5959. use Illuminate\Database\Eloquent\Relations\MorphTo;
  5960. use Illuminate\Support\Contracts\JsonableInterface;
  5961. use Illuminate\Support\Contracts\ArrayableInterface;
  5962. use Illuminate\Database\Eloquent\Relations\Relation;
  5963. use Illuminate\Database\Eloquent\Relations\MorphOne;
  5964. use Illuminate\Database\Eloquent\Relations\MorphMany;
  5965. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  5966. use Illuminate\Database\Query\Builder as QueryBuilder;
  5967. use Illuminate\Database\Eloquent\Relations\MorphToMany;
  5968. use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  5969. use Illuminate\Database\Eloquent\Relations\HasManyThrough;
  5970. use Illuminate\Database\ConnectionResolverInterface as Resolver;
  5971. abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterface, JsonSerializable
  5972. {
  5973. protected $connection;
  5974. protected $table;
  5975. protected $primaryKey = 'id';
  5976. protected $perPage = 15;
  5977. public $incrementing = true;
  5978. public $timestamps = true;
  5979. protected $attributes = array();
  5980. protected $original = array();
  5981. protected $relations = array();
  5982. protected $hidden = array();
  5983. protected $visible = array();
  5984. protected $appends = array();
  5985. protected $fillable = array();
  5986. protected $guarded = array('*');
  5987. protected $dates = array();
  5988. protected $touches = array();
  5989. protected $observables = array();
  5990. protected $with = array();
  5991. protected $morphClass;
  5992. public $exists = false;
  5993. public static $snakeAttributes = true;
  5994. protected static $resolver;
  5995. protected static $dispatcher;
  5996. protected static $booted = array();
  5997. protected static $globalScopes = array();
  5998. protected static $unguarded = false;
  5999. protected static $mutatorCache = array();
  6000. public static $manyMethods = array('belongsToMany', 'morphToMany', 'morphedByMany');
  6001. const CREATED_AT = 'created_at';
  6002. const UPDATED_AT = 'updated_at';
  6003. public function __construct(array $attributes = array())
  6004. {
  6005. $this->bootIfNotBooted();
  6006. $this->syncOriginal();
  6007. $this->fill($attributes);
  6008. }
  6009. protected function bootIfNotBooted()
  6010. {
  6011. if (!isset(static::$booted[get_class($this)])) {
  6012. static::$booted[get_class($this)] = true;
  6013. $this->fireModelEvent('booting', false);
  6014. static::boot();
  6015. $this->fireModelEvent('booted', false);
  6016. }
  6017. }
  6018. protected static function boot()
  6019. {
  6020. $class = get_called_class();
  6021. static::$mutatorCache[$class] = array();
  6022. foreach (get_class_methods($class) as $method) {
  6023. if (preg_match('/^get(.+)Attribute$/', $method, $matches)) {
  6024. if (static::$snakeAttributes) {
  6025. $matches[1] = snake_case($matches[1]);
  6026. }
  6027. static::$mutatorCache[$class][] = lcfirst($matches[1]);
  6028. }
  6029. }
  6030. static::bootTraits();
  6031. }
  6032. protected static function bootTraits()
  6033. {
  6034. foreach (class_uses(get_called_class()) as $trait) {
  6035. if (method_exists(get_called_class(), $method = 'boot' . class_basename($trait))) {
  6036. forward_static_call(array(get_called_class(), $method));
  6037. }
  6038. }
  6039. }
  6040. public static function addGlobalScope(ScopeInterface $scope)
  6041. {
  6042. static::$globalScopes[get_called_class()][get_class($scope)] = $scope;
  6043. }
  6044. public static function hasGlobalScope($scope)
  6045. {
  6046. return !is_null(static::getGlobalScope($scope));
  6047. }
  6048. public static function getGlobalScope($scope)
  6049. {
  6050. return array_first(static::$globalScopes[get_called_class()], function ($key, $value) use($scope) {
  6051. return $scope instanceof $value;
  6052. });
  6053. }
  6054. public function getGlobalScopes()
  6055. {
  6056. return array_get(static::$globalScopes, get_class($this), array());
  6057. }
  6058. public static function observe($class)
  6059. {
  6060. $instance = new static();
  6061. $className = get_class($class);
  6062. foreach ($instance->getObservableEvents() as $event) {
  6063. if (method_exists($class, $event)) {
  6064. static::registerModelEvent($event, $className . '@' . $event);
  6065. }
  6066. }
  6067. }
  6068. public function fill(array $attributes)
  6069. {
  6070. $totallyGuarded = $this->totallyGuarded();
  6071. foreach ($this->fillableFromArray($attributes) as $key => $value) {
  6072. $key = $this->removeTableFromKey($key);
  6073. if ($this->isFillable($key)) {
  6074. $this->setAttribute($key, $value);
  6075. } elseif ($totallyGuarded) {
  6076. throw new MassAssignmentException($key);
  6077. }
  6078. }
  6079. return $this;
  6080. }
  6081. protected function fillableFromArray(array $attributes)
  6082. {
  6083. if (count($this->fillable) > 0 && !static::$unguarded) {
  6084. return array_intersect_key($attributes, array_flip($this->fillable));
  6085. }
  6086. return $attributes;
  6087. }
  6088. public function newInstance($attributes = array(), $exists = false)
  6089. {
  6090. $model = new static((array) $attributes);
  6091. $model->exists = $exists;
  6092. return $model;
  6093. }
  6094. public function newFromBuilder($attributes = array())
  6095. {
  6096. $instance = $this->newInstance(array(), true);
  6097. $instance->setRawAttributes((array) $attributes, true);
  6098. return $instance;
  6099. }
  6100. public static function hydrate(array $items, $connection = null)
  6101. {
  6102. $collection = with($instance = new static())->newCollection();
  6103. foreach ($items as $item) {
  6104. $model = $instance->newFromBuilder($item);
  6105. if (!is_null($connection)) {
  6106. $model->setConnection($connection);
  6107. }
  6108. $collection->push($model);
  6109. }
  6110. return $collection;
  6111. }
  6112. public static function hydrateRaw($query, $bindings = array(), $connection = null)
  6113. {
  6114. $instance = new static();
  6115. if (!is_null($connection)) {
  6116. $instance->setConnection($connection);
  6117. }
  6118. $items = $instance->getConnection()->select($query, $bindings);
  6119. return static::hydrate($items, $connection);
  6120. }
  6121. public static function create(array $attributes)
  6122. {
  6123. $model = new static($attributes);
  6124. $model->save();
  6125. return $model;
  6126. }
  6127. public static function firstOrCreate(array $attributes)
  6128. {
  6129. if (!is_null($instance = static::firstByAttributes($attributes))) {
  6130. return $instance;
  6131. }
  6132. return static::create($attributes);
  6133. }
  6134. public static function firstOrNew(array $attributes)
  6135. {
  6136. if (!is_null($instance = static::firstByAttributes($attributes))) {
  6137. return $instance;
  6138. }
  6139. return new static($attributes);
  6140. }
  6141. public static function updateOrCreate(array $attributes, array $values = array())
  6142. {
  6143. $instance = static::firstOrNew($attributes);
  6144. $instance->fill($values)->save();
  6145. return $instance;
  6146. }
  6147. protected static function firstByAttributes($attributes)
  6148. {
  6149. $query = static::query();
  6150. foreach ($attributes as $key => $value) {
  6151. $query->where($key, $value);
  6152. }
  6153. return $query->first() ?: null;
  6154. }
  6155. public static function query()
  6156. {
  6157. return with(new static())->newQuery();
  6158. }
  6159. public static function on($connection = null)
  6160. {
  6161. $instance = new static();
  6162. $instance->setConnection($connection);
  6163. return $instance->newQuery();
  6164. }
  6165. public static function all($columns = array('*'))
  6166. {
  6167. $instance = new static();
  6168. return $instance->newQuery()->get($columns);
  6169. }
  6170. public static function find($id, $columns = array('*'))
  6171. {
  6172. if (is_array($id) && empty($id)) {
  6173. return new Collection();
  6174. }
  6175. $instance = new static();
  6176. return $instance->newQuery()->find($id, $columns);
  6177. }
  6178. public static function findOrNew($id, $columns = array('*'))
  6179. {
  6180. if (!is_null($model = static::find($id, $columns))) {
  6181. return $model;
  6182. }
  6183. return new static($columns);
  6184. }
  6185. public static function findOrFail($id, $columns = array('*'))
  6186. {
  6187. if (!is_null($model = static::find($id, $columns))) {
  6188. return $model;
  6189. }
  6190. throw with(new ModelNotFoundException())->setModel(get_called_class());
  6191. }
  6192. public function load($relations)
  6193. {
  6194. if (is_string($relations)) {
  6195. $relations = func_get_args();
  6196. }
  6197. $query = $this->newQuery()->with($relations);
  6198. $query->eagerLoadRelations(array($this));
  6199. return $this;
  6200. }
  6201. public static function with($relations)
  6202. {
  6203. if (is_string($relations)) {
  6204. $relations = func_get_args();
  6205. }
  6206. $instance = new static();
  6207. return $instance->newQuery()->with($relations);
  6208. }
  6209. public function hasOne($related, $foreignKey = null, $localKey = null)
  6210. {
  6211. $foreignKey = $foreignKey ?: $this->getForeignKey();
  6212. $instance = new $related();
  6213. $localKey = $localKey ?: $this->getKeyName();
  6214. return new HasOne($instance->newQuery(), $this, $instance->getTable() . '.' . $foreignKey, $localKey);
  6215. }
  6216. public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
  6217. {
  6218. $instance = new $related();
  6219. list($type, $id) = $this->getMorphs($name, $type, $id);
  6220. $table = $instance->getTable();
  6221. $localKey = $localKey ?: $this->getKeyName();
  6222. return new MorphOne($instance->newQuery(), $this, $table . '.' . $type, $table . '.' . $id, $localKey);
  6223. }
  6224. public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null)
  6225. {
  6226. if (is_null($relation)) {
  6227. list(, $caller) = debug_backtrace(false);
  6228. $relation = $caller['function'];
  6229. }
  6230. if (is_null($foreignKey)) {
  6231. $foreignKey = snake_case($relation) . '_id';
  6232. }
  6233. $instance = new $related();
  6234. $query = $instance->newQuery();
  6235. $otherKey = $otherKey ?: $instance->getKeyName();
  6236. return new BelongsTo($query, $this, $foreignKey, $otherKey, $relation);
  6237. }
  6238. public function morphTo($name = null, $type = null, $id = null)
  6239. {
  6240. if (is_null($name)) {
  6241. list(, $caller) = debug_backtrace(false);
  6242. $name = snake_case($caller['function']);
  6243. }
  6244. list($type, $id) = $this->getMorphs($name, $type, $id);
  6245. if (is_null($class = $this->{$type})) {
  6246. return new MorphTo($this->newQuery(), $this, $id, null, $type, $name);
  6247. } else {
  6248. $instance = new $class();
  6249. return new MorphTo(with($instance)->newQuery(), $this, $id, $instance->getKeyName(), $type, $name);
  6250. }
  6251. }
  6252. public function hasMany($related, $foreignKey = null, $localKey = null)
  6253. {
  6254. $foreignKey = $foreignKey ?: $this->getForeignKey();
  6255. $instance = new $related();
  6256. $localKey = $localKey ?: $this->getKeyName();
  6257. return new HasMany($instance->newQuery(), $this, $instance->getTable() . '.' . $foreignKey, $localKey);
  6258. }
  6259. public function hasManyThrough($related, $through, $firstKey = null, $secondKey = null)
  6260. {
  6261. $through = new $through();
  6262. $firstKey = $firstKey ?: $this->getForeignKey();
  6263. $secondKey = $secondKey ?: $through->getForeignKey();
  6264. return new HasManyThrough(with(new $related())->newQuery(), $this, $through, $firstKey, $secondKey);
  6265. }
  6266. public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
  6267. {
  6268. $instance = new $related();
  6269. list($type, $id) = $this->getMorphs($name, $type, $id);
  6270. $table = $instance->getTable();
  6271. $localKey = $localKey ?: $this->getKeyName();
  6272. return new MorphMany($instance->newQuery(), $this, $table . '.' . $type, $table . '.' . $id, $localKey);
  6273. }
  6274. public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
  6275. {
  6276. if (is_null($relation)) {
  6277. $relation = $this->getBelongsToManyCaller();
  6278. }
  6279. $foreignKey = $foreignKey ?: $this->getForeignKey();
  6280. $instance = new $related();
  6281. $otherKey = $otherKey ?: $instance->getForeignKey();
  6282. if (is_null($table)) {
  6283. $table = $this->joiningTable($related);
  6284. }
  6285. $query = $instance->newQuery();
  6286. return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation);
  6287. }
  6288. public function morphToMany($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false)
  6289. {
  6290. $caller = $this->getBelongsToManyCaller();
  6291. $foreignKey = $foreignKey ?: $name . '_id';
  6292. $instance = new $related();
  6293. $otherKey = $otherKey ?: $instance->getForeignKey();
  6294. $query = $instance->newQuery();
  6295. $table = $table ?: str_plural($name);
  6296. return new MorphToMany($query, $this, $name, $table, $foreignKey, $otherKey, $caller, $inverse);
  6297. }
  6298. public function morphedByMany($related, $name, $table = null, $foreignKey = null, $otherKey = null)
  6299. {
  6300. $foreignKey = $foreignKey ?: $this->getForeignKey();
  6301. $otherKey = $otherKey ?: $name . '_id';
  6302. return $this->morphToMany($related, $name, $table, $foreignKey, $otherKey, true);
  6303. }
  6304. protected function getBelongsToManyCaller()
  6305. {
  6306. $self = __FUNCTION__;
  6307. $caller = array_first(debug_backtrace(false), function ($key, $trace) use($self) {
  6308. $caller = $trace['function'];
  6309. return !in_array($caller, Model::$manyMethods) && $caller != $self;
  6310. });
  6311. return !is_null($caller) ? $caller['function'] : null;
  6312. }
  6313. public function joiningTable($related)
  6314. {
  6315. $base = snake_case(class_basename($this));
  6316. $related = snake_case(class_basename($related));
  6317. $models = array($related, $base);
  6318. sort($models);
  6319. return strtolower(implode('_', $models));
  6320. }
  6321. public static function destroy($ids)
  6322. {
  6323. $count = 0;
  6324. $ids = is_array($ids) ? $ids : func_get_args();
  6325. $instance = new static();
  6326. $key = $instance->getKeyName();
  6327. foreach ($instance->whereIn($key, $ids)->get() as $model) {
  6328. if ($model->delete()) {
  6329. $count++;
  6330. }
  6331. }
  6332. return $count;
  6333. }
  6334. public function delete()
  6335. {
  6336. if (is_null($this->primaryKey)) {
  6337. throw new \Exception('No primary key defined on model.');
  6338. }
  6339. if ($this->exists) {
  6340. if ($this->fireModelEvent('deleting') === false) {
  6341. return false;
  6342. }
  6343. $this->touchOwners();
  6344. $this->performDeleteOnModel();
  6345. $this->exists = false;
  6346. $this->fireModelEvent('deleted', false);
  6347. return true;
  6348. }
  6349. }
  6350. protected function performDeleteOnModel()
  6351. {
  6352. $this->newQuery()->where($this->getKeyName(), $this->getKey())->delete();
  6353. }
  6354. public static function saving($callback)
  6355. {
  6356. static::registerModelEvent('saving', $callback);
  6357. }
  6358. public static function saved($callback)
  6359. {
  6360. static::registerModelEvent('saved', $callback);
  6361. }
  6362. public static function updating($callback)
  6363. {
  6364. static::registerModelEvent('updating', $callback);
  6365. }
  6366. public static function updated($callback)
  6367. {
  6368. static::registerModelEvent('updated', $callback);
  6369. }
  6370. public static function creating($callback)
  6371. {
  6372. static::registerModelEvent('creating', $callback);
  6373. }
  6374. public static function created($callback)
  6375. {
  6376. static::registerModelEvent('created', $callback);
  6377. }
  6378. public static function deleting($callback)
  6379. {
  6380. static::registerModelEvent('deleting', $callback);
  6381. }
  6382. public static function deleted($callback)
  6383. {
  6384. static::registerModelEvent('deleted', $callback);
  6385. }
  6386. public static function flushEventListeners()
  6387. {
  6388. if (!isset(static::$dispatcher)) {
  6389. return;
  6390. }
  6391. $instance = new static();
  6392. foreach ($instance->getObservableEvents() as $event) {
  6393. static::$dispatcher->forget("eloquent.{$event}: " . get_called_class());
  6394. }
  6395. }
  6396. protected static function registerModelEvent($event, $callback)
  6397. {
  6398. if (isset(static::$dispatcher)) {
  6399. $name = get_called_class();
  6400. static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
  6401. }
  6402. }
  6403. public function getObservableEvents()
  6404. {
  6405. return array_merge(array('creating', 'created', 'updating', 'updated', 'deleting', 'deleted', 'saving', 'saved', 'restoring', 'restored'), $this->observables);
  6406. }
  6407. protected function increment($column, $amount = 1)
  6408. {
  6409. return $this->incrementOrDecrement($column, $amount, 'increment');
  6410. }
  6411. protected function decrement($column, $amount = 1)
  6412. {
  6413. return $this->incrementOrDecrement($column, $amount, 'decrement');
  6414. }
  6415. protected function incrementOrDecrement($column, $amount, $method)
  6416. {
  6417. $query = $this->newQuery();
  6418. if (!$this->exists) {
  6419. return $query->{$method}($column, $amount);
  6420. }
  6421. return $query->where($this->getKeyName(), $this->getKey())->{$method}($column, $amount);
  6422. }
  6423. public function update(array $attributes = array())
  6424. {
  6425. if (!$this->exists) {
  6426. return $this->newQuery()->update($attributes);
  6427. }
  6428. return $this->fill($attributes)->save();
  6429. }
  6430. public function push()
  6431. {
  6432. if (!$this->save()) {
  6433. return false;
  6434. }
  6435. foreach ($this->relations as $models) {
  6436. foreach (Collection::make($models) as $model) {
  6437. if (!$model->push()) {
  6438. return false;
  6439. }
  6440. }
  6441. }
  6442. return true;
  6443. }
  6444. public function save(array $options = array())
  6445. {
  6446. $query = $this->newQueryWithoutScopes();
  6447. if ($this->fireModelEvent('saving') === false) {
  6448. return false;
  6449. }
  6450. if ($this->exists) {
  6451. $saved = $this->performUpdate($query);
  6452. } else {
  6453. $saved = $this->performInsert($query);
  6454. }
  6455. if ($saved) {
  6456. $this->finishSave($options);
  6457. }
  6458. return $saved;
  6459. }
  6460. protected function finishSave(array $options)
  6461. {
  6462. $this->fireModelEvent('saved', false);
  6463. $this->syncOriginal();
  6464. if (array_get($options, 'touch', true)) {
  6465. $this->touchOwners();
  6466. }
  6467. }
  6468. protected function performUpdate(Builder $query)
  6469. {
  6470. $dirty = $this->getDirty();
  6471. if (count($dirty) > 0) {
  6472. if ($this->fireModelEvent('updating') === false) {
  6473. return false;
  6474. }
  6475. if ($this->timestamps) {
  6476. $this->updateTimestamps();
  6477. }
  6478. $dirty = $this->getDirty();
  6479. if (count($dirty) > 0) {
  6480. $this->setKeysForSaveQuery($query)->update($dirty);
  6481. $this->fireModelEvent('updated', false);
  6482. }
  6483. }
  6484. return true;
  6485. }
  6486. protected function performInsert(Builder $query)
  6487. {
  6488. if ($this->fireModelEvent('creating') === false) {
  6489. return false;
  6490. }
  6491. if ($this->timestamps) {
  6492. $this->updateTimestamps();
  6493. }
  6494. $attributes = $this->attributes;
  6495. if ($this->incrementing) {
  6496. $this->insertAndSetId($query, $attributes);
  6497. } else {
  6498. $query->insert($attributes);
  6499. }
  6500. $this->exists = true;
  6501. $this->fireModelEvent('created', false);
  6502. return true;
  6503. }
  6504. protected function insertAndSetId(Builder $query, $attributes)
  6505. {
  6506. $id = $query->insertGetId($attributes, $keyName = $this->getKeyName());
  6507. $this->setAttribute($keyName, $id);
  6508. }
  6509. public function touchOwners()
  6510. {
  6511. foreach ($this->touches as $relation) {
  6512. $this->{$relation}()->touch();
  6513. }
  6514. }
  6515. public function touches($relation)
  6516. {
  6517. return in_array($relation, $this->touches);
  6518. }
  6519. protected function fireModelEvent($event, $halt = true)
  6520. {
  6521. if (!isset(static::$dispatcher)) {
  6522. return true;
  6523. }
  6524. $event = "eloquent.{$event}: " . get_class($this);
  6525. $method = $halt ? 'until' : 'fire';
  6526. return static::$dispatcher->{$method}($event, $this);
  6527. }
  6528. protected function setKeysForSaveQuery(Builder $query)
  6529. {
  6530. $query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery());
  6531. return $query;
  6532. }
  6533. protected function getKeyForSaveQuery()
  6534. {
  6535. if (isset($this->original[$this->getKeyName()])) {
  6536. return $this->original[$this->getKeyName()];
  6537. } else {
  6538. return $this->getAttribute($this->getKeyName());
  6539. }
  6540. }
  6541. public function touch()
  6542. {
  6543. $this->updateTimestamps();
  6544. return $this->save();
  6545. }
  6546. protected function updateTimestamps()
  6547. {
  6548. $time = $this->freshTimestamp();
  6549. if (!$this->isDirty(static::UPDATED_AT)) {
  6550. $this->setUpdatedAt($time);
  6551. }
  6552. if (!$this->exists && !$this->isDirty(static::CREATED_AT)) {
  6553. $this->setCreatedAt($time);
  6554. }
  6555. }
  6556. public function setCreatedAt($value)
  6557. {
  6558. $this->{static::CREATED_AT} = $value;
  6559. }
  6560. public function setUpdatedAt($value)
  6561. {
  6562. $this->{static::UPDATED_AT} = $value;
  6563. }
  6564. public function getCreatedAtColumn()
  6565. {
  6566. return static::CREATED_AT;
  6567. }
  6568. public function getUpdatedAtColumn()
  6569. {
  6570. return static::UPDATED_AT;
  6571. }
  6572. public function freshTimestamp()
  6573. {
  6574. return new Carbon();
  6575. }
  6576. public function freshTimestampString()
  6577. {
  6578. return $this->fromDateTime($this->freshTimestamp());
  6579. }
  6580. public function newQuery()
  6581. {
  6582. $builder = $this->newEloquentBuilder($this->newBaseQueryBuilder());
  6583. $builder->setModel($this)->with($this->with);
  6584. return $this->applyGlobalScopes($builder);
  6585. }
  6586. public function newQueryWithoutScope($scope)
  6587. {
  6588. $this->getGlobalScope($scope)->remove($builder = $this->newQuery(), $this);
  6589. return $builder;
  6590. }
  6591. public function newQueryWithoutScopes()
  6592. {
  6593. return $this->removeGlobalScopes($this->newQuery());
  6594. }
  6595. public function applyGlobalScopes($builder)
  6596. {
  6597. foreach ($this->getGlobalScopes() as $scope) {
  6598. $scope->apply($builder, $this);
  6599. }
  6600. return $builder;
  6601. }
  6602. public function removeGlobalScopes($builder)
  6603. {
  6604. foreach ($this->getGlobalScopes() as $scope) {
  6605. $scope->remove($builder, $this);
  6606. }
  6607. return $builder;
  6608. }
  6609. public function newEloquentBuilder($query)
  6610. {
  6611. return new Builder($query);
  6612. }
  6613. protected function newBaseQueryBuilder()
  6614. {
  6615. $conn = $this->getConnection();
  6616. $grammar = $conn->getQueryGrammar();
  6617. return new QueryBuilder($conn, $grammar, $conn->getPostProcessor());
  6618. }
  6619. public function newCollection(array $models = array())
  6620. {
  6621. return new Collection($models);
  6622. }
  6623. public function newPivot(Model $parent, array $attributes, $table, $exists)
  6624. {
  6625. return new Pivot($parent, $attributes, $table, $exists);
  6626. }
  6627. public function getTable()
  6628. {
  6629. if (isset($this->table)) {
  6630. return $this->table;
  6631. }
  6632. return str_replace('\\', '', snake_case(str_plural(class_basename($this))));
  6633. }
  6634. public function setTable($table)
  6635. {
  6636. $this->table = $table;
  6637. }
  6638. public function getKey()
  6639. {
  6640. return $this->getAttribute($this->getKeyName());
  6641. }
  6642. public function getKeyName()
  6643. {
  6644. return $this->primaryKey;
  6645. }
  6646. public function getQualifiedKeyName()
  6647. {
  6648. return $this->getTable() . '.' . $this->getKeyName();
  6649. }
  6650. public function usesTimestamps()
  6651. {
  6652. return $this->timestamps;
  6653. }
  6654. protected function getMorphs($name, $type, $id)
  6655. {
  6656. $type = $type ?: $name . '_type';
  6657. $id = $id ?: $name . '_id';
  6658. return array($type, $id);
  6659. }
  6660. public function getMorphClass()
  6661. {
  6662. return $this->morphClass ?: get_class($this);
  6663. }
  6664. public function getPerPage()
  6665. {
  6666. return $this->perPage;
  6667. }
  6668. public function setPerPage($perPage)
  6669. {
  6670. $this->perPage = $perPage;
  6671. }
  6672. public function getForeignKey()
  6673. {
  6674. return snake_case(class_basename($this)) . '_id';
  6675. }
  6676. public function getHidden()
  6677. {
  6678. return $this->hidden;
  6679. }
  6680. public function setHidden(array $hidden)
  6681. {
  6682. $this->hidden = $hidden;
  6683. }
  6684. public function setVisible(array $visible)
  6685. {
  6686. $this->visible = $visible;
  6687. }
  6688. public function setAppends(array $appends)
  6689. {
  6690. $this->appends = $appends;
  6691. }
  6692. public function getFillable()
  6693. {
  6694. return $this->fillable;
  6695. }
  6696. public function fillable(array $fillable)
  6697. {
  6698. $this->fillable = $fillable;
  6699. return $this;
  6700. }
  6701. public function guard(array $guarded)
  6702. {
  6703. $this->guarded = $guarded;
  6704. return $this;
  6705. }
  6706. public static function unguard()
  6707. {
  6708. static::$unguarded = true;
  6709. }
  6710. public static function reguard()
  6711. {
  6712. static::$unguarded = false;
  6713. }
  6714. public static function setUnguardState($state)
  6715. {
  6716. static::$unguarded = $state;
  6717. }
  6718. public function isFillable($key)
  6719. {
  6720. if (static::$unguarded) {
  6721. return true;
  6722. }
  6723. if (in_array($key, $this->fillable)) {
  6724. return true;
  6725. }
  6726. if ($this->isGuarded($key)) {
  6727. return false;
  6728. }
  6729. return empty($this->fillable) && !starts_with($key, '_');
  6730. }
  6731. public function isGuarded($key)
  6732. {
  6733. return in_array($key, $this->guarded) || $this->guarded == array('*');
  6734. }
  6735. public function totallyGuarded()
  6736. {
  6737. return count($this->fillable) == 0 && $this->guarded == array('*');
  6738. }
  6739. protected function removeTableFromKey($key)
  6740. {
  6741. if (!str_contains($key, '.')) {
  6742. return $key;
  6743. }
  6744. return last(explode('.', $key));
  6745. }
  6746. public function getTouchedRelations()
  6747. {
  6748. return $this->touches;
  6749. }
  6750. public function setTouchedRelations(array $touches)
  6751. {
  6752. $this->touches = $touches;
  6753. }
  6754. public function getIncrementing()
  6755. {
  6756. return $this->incrementing;
  6757. }
  6758. public function setIncrementing($value)
  6759. {
  6760. $this->incrementing = $value;
  6761. }
  6762. public function toJson($options = 0)
  6763. {
  6764. return json_encode($this->toArray(), $options);
  6765. }
  6766. public function jsonSerialize()
  6767. {
  6768. return $this->toArray();
  6769. }
  6770. public function toArray()
  6771. {
  6772. $attributes = $this->attributesToArray();
  6773. return array_merge($attributes, $this->relationsToArray());
  6774. }
  6775. public function attributesToArray()
  6776. {
  6777. $attributes = $this->getArrayableAttributes();
  6778. foreach ($this->getDates() as $key) {
  6779. if (!isset($attributes[$key])) {
  6780. continue;
  6781. }
  6782. $attributes[$key] = (string) $this->asDateTime($attributes[$key]);
  6783. }
  6784. foreach ($this->getMutatedAttributes() as $key) {
  6785. if (!array_key_exists($key, $attributes)) {
  6786. continue;
  6787. }
  6788. $attributes[$key] = $this->mutateAttributeForArray($key, $attributes[$key]);
  6789. }
  6790. foreach ($this->appends as $key) {
  6791. $attributes[$key] = $this->mutateAttributeForArray($key, null);
  6792. }
  6793. return $attributes;
  6794. }
  6795. protected function getArrayableAttributes()
  6796. {
  6797. return $this->getArrayableItems($this->attributes);
  6798. }
  6799. public function relationsToArray()
  6800. {
  6801. $attributes = array();
  6802. foreach ($this->getArrayableRelations() as $key => $value) {
  6803. if (in_array($key, $this->hidden)) {
  6804. continue;
  6805. }
  6806. if ($value instanceof ArrayableInterface) {
  6807. $relation = $value->toArray();
  6808. } elseif (is_null($value)) {
  6809. $relation = $value;
  6810. }
  6811. if (static::$snakeAttributes) {
  6812. $key = snake_case($key);
  6813. }
  6814. if (isset($relation) || is_null($value)) {
  6815. $attributes[$key] = $relation;
  6816. }
  6817. }
  6818. return $attributes;
  6819. }
  6820. protected function getArrayableRelations()
  6821. {
  6822. return $this->getArrayableItems($this->relations);
  6823. }
  6824. protected function getArrayableItems(array $values)
  6825. {
  6826. if (count($this->visible) > 0) {
  6827. return array_intersect_key($values, array_flip($this->visible));
  6828. }
  6829. return array_diff_key($values, array_flip($this->hidden));
  6830. }
  6831. public function getAttribute($key)
  6832. {
  6833. $inAttributes = array_key_exists($key, $this->attributes);
  6834. if ($inAttributes || $this->hasGetMutator($key)) {
  6835. return $this->getAttributeValue($key);
  6836. }
  6837. if (array_key_exists($key, $this->relations)) {
  6838. return $this->relations[$key];
  6839. }
  6840. $camelKey = camel_case($key);
  6841. if (method_exists($this, $camelKey)) {
  6842. return $this->getRelationshipFromMethod($key, $camelKey);
  6843. }
  6844. }
  6845. protected function getAttributeValue($key)
  6846. {
  6847. $value = $this->getAttributeFromArray($key);
  6848. if ($this->hasGetMutator($key)) {
  6849. return $this->mutateAttribute($key, $value);
  6850. } elseif (in_array($key, $this->getDates())) {
  6851. if ($value) {
  6852. return $this->asDateTime($value);
  6853. }
  6854. }
  6855. return $value;
  6856. }
  6857. protected function getAttributeFromArray($key)
  6858. {
  6859. if (array_key_exists($key, $this->attributes)) {
  6860. return $this->attributes[$key];
  6861. }
  6862. }
  6863. protected function getRelationshipFromMethod($key, $camelKey)
  6864. {
  6865. $relations = $this->{$camelKey}();
  6866. if (!$relations instanceof Relation) {
  6867. throw new LogicException('Relationship method must return an object of type ' . 'Illuminate\\Database\\Eloquent\\Relations\\Relation');
  6868. }
  6869. return $this->relations[$key] = $relations->getResults();
  6870. }
  6871. public function hasGetMutator($key)
  6872. {
  6873. return method_exists($this, 'get' . studly_case($key) . 'Attribute');
  6874. }
  6875. protected function mutateAttribute($key, $value)
  6876. {
  6877. return $this->{'get' . studly_case($key) . 'Attribute'}($value);
  6878. }
  6879. protected function mutateAttributeForArray($key, $value)
  6880. {
  6881. $value = $this->mutateAttribute($key, $value);
  6882. return $value instanceof ArrayableInterface ? $value->toArray() : $value;
  6883. }
  6884. public function setAttribute($key, $value)
  6885. {
  6886. if ($this->hasSetMutator($key)) {
  6887. $method = 'set' . studly_case($key) . 'Attribute';
  6888. return $this->{$method}($value);
  6889. } elseif (in_array($key, $this->getDates())) {
  6890. if ($value) {
  6891. $value = $this->fromDateTime($value);
  6892. }
  6893. }
  6894. $this->attributes[$key] = $value;
  6895. }
  6896. public function hasSetMutator($key)
  6897. {
  6898. return method_exists($this, 'set' . studly_case($key) . 'Attribute');
  6899. }
  6900. public function getDates()
  6901. {
  6902. $defaults = array(static::CREATED_AT, static::UPDATED_AT);
  6903. return array_merge($this->dates, $defaults);
  6904. }
  6905. public function fromDateTime($value)
  6906. {
  6907. $format = $this->getDateFormat();
  6908. if ($value instanceof DateTime) {
  6909. } elseif (is_numeric($value)) {
  6910. $value = Carbon::createFromTimestamp($value);
  6911. } elseif (preg_match('/^(\\d{4})-(\\d{2})-(\\d{2})$/', $value)) {
  6912. $value = Carbon::createFromFormat('Y-m-d', $value)->startOfDay();
  6913. } elseif (!$value instanceof DateTime) {
  6914. $value = Carbon::createFromFormat($format, $value);
  6915. }
  6916. return $value->format($format);
  6917. }
  6918. protected function asDateTime($value)
  6919. {
  6920. if (is_numeric($value)) {
  6921. return Carbon::createFromTimestamp($value);
  6922. } elseif (preg_match('/^(\\d{4})-(\\d{2})-(\\d{2})$/', $value)) {
  6923. return Carbon::createFromFormat('Y-m-d', $value)->startOfDay();
  6924. } elseif (!$value instanceof DateTime) {
  6925. $format = $this->getDateFormat();
  6926. return Carbon::createFromFormat($format, $value);
  6927. }
  6928. return Carbon::instance($value);
  6929. }
  6930. protected function getDateFormat()
  6931. {
  6932. return $this->getConnection()->getQueryGrammar()->getDateFormat();
  6933. }
  6934. public function replicate()
  6935. {
  6936. $attributes = array_except($this->attributes, array($this->getKeyName()));
  6937. with($instance = new static())->setRawAttributes($attributes);
  6938. return $instance->setRelations($this->relations);
  6939. }
  6940. public function getAttributes()
  6941. {
  6942. return $this->attributes;
  6943. }
  6944. public function setRawAttributes(array $attributes, $sync = false)
  6945. {
  6946. $this->attributes = $attributes;
  6947. if ($sync) {
  6948. $this->syncOriginal();
  6949. }
  6950. }
  6951. public function getOriginal($key = null, $default = null)
  6952. {
  6953. return array_get($this->original, $key, $default);
  6954. }
  6955. public function syncOriginal()
  6956. {
  6957. $this->original = $this->attributes;
  6958. return $this;
  6959. }
  6960. public function isDirty($attribute = null)
  6961. {
  6962. $dirty = $this->getDirty();
  6963. if (is_null($attribute)) {
  6964. return count($dirty) > 0;
  6965. } else {
  6966. return array_key_exists($attribute, $dirty);
  6967. }
  6968. }
  6969. public function getDirty()
  6970. {
  6971. $dirty = array();
  6972. foreach ($this->attributes as $key => $value) {
  6973. if (!array_key_exists($key, $this->original)) {
  6974. $dirty[$key] = $value;
  6975. } elseif ($value !== $this->original[$key] && !$this->originalIsNumericallyEquivalent($key)) {
  6976. $dirty[$key] = $value;
  6977. }
  6978. }
  6979. return $dirty;
  6980. }
  6981. protected function originalIsNumericallyEquivalent($key)
  6982. {
  6983. $current = $this->attributes[$key];
  6984. $original = $this->original[$key];
  6985. return is_numeric($current) && is_numeric($original) && strcmp((string) $current, (string) $original) === 0;
  6986. }
  6987. public function getRelations()
  6988. {
  6989. return $this->relations;
  6990. }
  6991. public function getRelation($relation)
  6992. {
  6993. return $this->relations[$relation];
  6994. }
  6995. public function setRelation($relation, $value)
  6996. {
  6997. $this->relations[$relation] = $value;
  6998. return $this;
  6999. }
  7000. public function setRelations(array $relations)
  7001. {
  7002. $this->relations = $relations;
  7003. return $this;
  7004. }
  7005. public function getConnection()
  7006. {
  7007. return static::resolveConnection($this->connection);
  7008. }
  7009. public function getConnectionName()
  7010. {
  7011. return $this->connection;
  7012. }
  7013. public function setConnection($name)
  7014. {
  7015. $this->connection = $name;
  7016. return $this;
  7017. }
  7018. public static function resolveConnection($connection = null)
  7019. {
  7020. return static::$resolver->connection($connection);
  7021. }
  7022. public static function getConnectionResolver()
  7023. {
  7024. return static::$resolver;
  7025. }
  7026. public static function setConnectionResolver(Resolver $resolver)
  7027. {
  7028. static::$resolver = $resolver;
  7029. }
  7030. public static function unsetConnectionResolver()
  7031. {
  7032. static::$resolver = null;
  7033. }
  7034. public static function getEventDispatcher()
  7035. {
  7036. return static::$dispatcher;
  7037. }
  7038. public static function setEventDispatcher(Dispatcher $dispatcher)
  7039. {
  7040. static::$dispatcher = $dispatcher;
  7041. }
  7042. public static function unsetEventDispatcher()
  7043. {
  7044. static::$dispatcher = null;
  7045. }
  7046. public function getMutatedAttributes()
  7047. {
  7048. $class = get_class($this);
  7049. if (isset(static::$mutatorCache[$class])) {
  7050. return static::$mutatorCache[get_class($this)];
  7051. }
  7052. return array();
  7053. }
  7054. public function __get($key)
  7055. {
  7056. return $this->getAttribute($key);
  7057. }
  7058. public function __set($key, $value)
  7059. {
  7060. $this->setAttribute($key, $value);
  7061. }
  7062. public function offsetExists($offset)
  7063. {
  7064. return isset($this->{$offset});
  7065. }
  7066. public function offsetGet($offset)
  7067. {
  7068. return $this->{$offset};
  7069. }
  7070. public function offsetSet($offset, $value)
  7071. {
  7072. $this->{$offset} = $value;
  7073. }
  7074. public function offsetUnset($offset)
  7075. {
  7076. unset($this->{$offset});
  7077. }
  7078. public function __isset($key)
  7079. {
  7080. return isset($this->attributes[$key]) || isset($this->relations[$key]) || $this->hasGetMutator($key) && !is_null($this->getAttributeValue($key));
  7081. }
  7082. public function __unset($key)
  7083. {
  7084. unset($this->attributes[$key]);
  7085. unset($this->relations[$key]);
  7086. }
  7087. public function __call($method, $parameters)
  7088. {
  7089. if (in_array($method, array('increment', 'decrement'))) {
  7090. return call_user_func_array(array($this, $method), $parameters);
  7091. }
  7092. $query = $this->newQuery();
  7093. return call_user_func_array(array($query, $method), $parameters);
  7094. }
  7095. public static function __callStatic($method, $parameters)
  7096. {
  7097. $instance = new static();
  7098. return call_user_func_array(array($instance, $method), $parameters);
  7099. }
  7100. public function __toString()
  7101. {
  7102. return $this->toJson();
  7103. }
  7104. public function __wakeup()
  7105. {
  7106. $this->bootIfNotBooted();
  7107. }
  7108. }
  7109. namespace Illuminate\Support\Contracts;
  7110. interface ArrayableInterface
  7111. {
  7112. public function toArray();
  7113. }
  7114. namespace Illuminate\Support\Contracts;
  7115. interface JsonableInterface
  7116. {
  7117. public function toJson($options = 0);
  7118. }
  7119. namespace Illuminate\Database;
  7120. use Illuminate\Database\Connectors\ConnectionFactory;
  7121. class DatabaseManager implements ConnectionResolverInterface
  7122. {
  7123. protected $app;
  7124. protected $factory;
  7125. protected $connections = array();
  7126. protected $extensions = array();
  7127. public function __construct($app, ConnectionFactory $factory)
  7128. {
  7129. $this->app = $app;
  7130. $this->factory = $factory;
  7131. }
  7132. public function connection($name = null)
  7133. {
  7134. $name = $name ?: $this->getDefaultConnection();
  7135. if (!isset($this->connections[$name])) {
  7136. $connection = $this->makeConnection($name);
  7137. $this->connections[$name] = $this->prepare($connection);
  7138. }
  7139. return $this->connections[$name];
  7140. }
  7141. public function reconnect($name = null)
  7142. {
  7143. $name = $name ?: $this->getDefaultConnection();
  7144. $this->disconnect($name);
  7145. return $this->connection($name);
  7146. }
  7147. public function disconnect($name = null)
  7148. {
  7149. $name = $name ?: $this->getDefaultConnection();
  7150. unset($this->connections[$name]);
  7151. }
  7152. protected function makeConnection($name)
  7153. {
  7154. $config = $this->getConfig($name);
  7155. if (isset($this->extensions[$name])) {
  7156. return call_user_func($this->extensions[$name], $config, $name);
  7157. }
  7158. $driver = $config['driver'];
  7159. if (isset($this->extensions[$driver])) {
  7160. return call_user_func($this->extensions[$driver], $config, $name);
  7161. }
  7162. return $this->factory->make($config, $name);
  7163. }
  7164. protected function prepare(Connection $connection)
  7165. {
  7166. $connection->setFetchMode($this->app['config']['database.fetch']);
  7167. if ($this->app->bound('events')) {
  7168. $connection->setEventDispatcher($this->app['events']);
  7169. }
  7170. $app = $this->app;
  7171. $connection->setCacheManager(function () use($app) {
  7172. return $app['cache'];
  7173. });
  7174. $connection->setPaginator(function () use($app) {
  7175. return $app['paginator'];
  7176. });
  7177. return $connection;
  7178. }
  7179. protected function getConfig($name)
  7180. {
  7181. $name = $name ?: $this->getDefaultConnection();
  7182. $connections = $this->app['config']['database.connections'];
  7183. if (is_null($config = array_get($connections, $name))) {
  7184. throw new \InvalidArgumentException("Database [{$name}] not configured.");
  7185. }
  7186. return $config;
  7187. }
  7188. public function getDefaultConnection()
  7189. {
  7190. return $this->app['config']['database.default'];
  7191. }
  7192. public function setDefaultConnection($name)
  7193. {
  7194. $this->app['config']['database.default'] = $name;
  7195. }
  7196. public function extend($name, $resolver)
  7197. {
  7198. $this->extensions[$name] = $resolver;
  7199. }
  7200. public function getConnections()
  7201. {
  7202. return $this->connections;
  7203. }
  7204. public function __call($method, $parameters)
  7205. {
  7206. return call_user_func_array(array($this->connection(), $method), $parameters);
  7207. }
  7208. }
  7209. namespace Illuminate\Database;
  7210. interface ConnectionResolverInterface
  7211. {
  7212. public function connection($name = null);
  7213. public function getDefaultConnection();
  7214. public function setDefaultConnection($name);
  7215. }
  7216. namespace Illuminate\Database\Connectors;
  7217. use PDO;
  7218. use Illuminate\Container\Container;
  7219. use Illuminate\Database\MySqlConnection;
  7220. use Illuminate\Database\SQLiteConnection;
  7221. use Illuminate\Database\PostgresConnection;
  7222. use Illuminate\Database\SqlServerConnection;
  7223. class ConnectionFactory
  7224. {
  7225. protected $container;
  7226. public function __construct(Container $container)
  7227. {
  7228. $this->container = $container;
  7229. }
  7230. public function make(array $config, $name = null)
  7231. {
  7232. $config = $this->parseConfig($config, $name);
  7233. if (isset($config['read'])) {
  7234. return $this->createReadWriteConnection($config);
  7235. } else {
  7236. return $this->createSingleConnection($config);
  7237. }
  7238. }
  7239. protected function createSingleConnection(array $config)
  7240. {
  7241. $pdo = $this->createConnector($config)->connect($config);
  7242. return $this->createConnection($config['driver'], $pdo, $config['database'], $config['prefix'], $config);
  7243. }
  7244. protected function createReadWriteConnection(array $config)
  7245. {
  7246. $connection = $this->createSingleConnection($this->getWriteConfig($config));
  7247. return $connection->setReadPdo($this->createReadPdo($config));
  7248. }
  7249. protected function createReadPdo(array $config)
  7250. {
  7251. $readConfig = $this->getReadConfig($config);
  7252. return $this->createConnector($readConfig)->connect($readConfig);
  7253. }
  7254. protected function getReadConfig(array $config)
  7255. {
  7256. $readConfig = $this->getReadWriteConfig($config, 'read');
  7257. return $this->mergeReadWriteConfig($config, $readConfig);
  7258. }
  7259. protected function getWriteConfig(array $config)
  7260. {
  7261. $writeConfig = $this->getReadWriteConfig($config, 'write');
  7262. return $this->mergeReadWriteConfig($config, $writeConfig);
  7263. }
  7264. protected function getReadWriteConfig(array $config, $type)
  7265. {
  7266. if (isset($config[$type][0])) {
  7267. return $config[$type][array_rand($config[$type])];
  7268. } else {
  7269. return $config[$type];
  7270. }
  7271. }
  7272. protected function mergeReadWriteConfig(array $config, array $merge)
  7273. {
  7274. return array_except(array_merge($config, $merge), array('read', 'write'));
  7275. }
  7276. protected function parseConfig(array $config, $name)
  7277. {
  7278. return array_add(array_add($config, 'prefix', ''), 'name', $name);
  7279. }
  7280. public function createConnector(array $config)
  7281. {
  7282. if (!isset($config['driver'])) {
  7283. throw new \InvalidArgumentException('A driver must be specified.');
  7284. }
  7285. if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
  7286. return $this->container->make($key);
  7287. }
  7288. switch ($config['driver']) {
  7289. case 'mysql':
  7290. return new MySqlConnector();
  7291. case 'pgsql':
  7292. return new PostgresConnector();
  7293. case 'sqlite':
  7294. return new SQLiteConnector();
  7295. case 'sqlsrv':
  7296. return new SqlServerConnector();
  7297. }
  7298. throw new \InvalidArgumentException("Unsupported driver [{$config['driver']}]");
  7299. }
  7300. protected function createConnection($driver, PDO $connection, $database, $prefix = '', array $config = array())
  7301. {
  7302. if ($this->container->bound($key = "db.connection.{$driver}")) {
  7303. return $this->container->make($key, array($connection, $database, $prefix, $config));
  7304. }
  7305. switch ($driver) {
  7306. case 'mysql':
  7307. return new MySqlConnection($connection, $database, $prefix, $config);
  7308. case 'pgsql':
  7309. return new PostgresConnection($connection, $database, $prefix, $config);
  7310. case 'sqlite':
  7311. return new SQLiteConnection($connection, $database, $prefix, $config);
  7312. case 'sqlsrv':
  7313. return new SqlServerConnection($connection, $database, $prefix, $config);
  7314. }
  7315. throw new \InvalidArgumentException("Unsupported driver [{$driver}]");
  7316. }
  7317. }
  7318. namespace Illuminate\Session;
  7319. use Closure;
  7320. use Carbon\Carbon;
  7321. use Symfony\Component\HttpFoundation\Cookie;
  7322. use Symfony\Component\HttpFoundation\Request;
  7323. use Symfony\Component\HttpFoundation\Response;
  7324. use Symfony\Component\HttpKernel\HttpKernelInterface;
  7325. class Middleware implements HttpKernelInterface
  7326. {
  7327. protected $app;
  7328. protected $manager;
  7329. protected $reject;
  7330. public function __construct(HttpKernelInterface $app, SessionManager $manager, Closure $reject = null)
  7331. {
  7332. $this->app = $app;
  7333. $this->reject = $reject;
  7334. $this->manager = $manager;
  7335. }
  7336. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  7337. {
  7338. $this->checkRequestForArraySessions($request);
  7339. if ($this->sessionConfigured()) {
  7340. $session = $this->startSession($request);
  7341. $request->setSession($session);
  7342. }
  7343. $response = $this->app->handle($request, $type, $catch);
  7344. if ($this->sessionConfigured()) {
  7345. $this->closeSession($session);
  7346. $this->addCookieToResponse($response, $session);
  7347. }
  7348. return $response;
  7349. }
  7350. public function checkRequestForArraySessions(Request $request)
  7351. {
  7352. if (is_null($this->reject)) {
  7353. return;
  7354. }
  7355. if (call_user_func($this->reject, $request)) {
  7356. $this->manager->setDefaultDriver('array');
  7357. }
  7358. }
  7359. protected function startSession(Request $request)
  7360. {
  7361. with($session = $this->getSession($request))->setRequestOnHandler($request);
  7362. $session->start();
  7363. return $session;
  7364. }
  7365. protected function closeSession(SessionInterface $session)
  7366. {
  7367. $session->save();
  7368. $this->collectGarbage($session);
  7369. }
  7370. protected function getUrl(Request $request)
  7371. {
  7372. $url = rtrim(preg_replace('/\\?.*/', '', $request->getUri()), '/');
  7373. return $request->getQueryString() ? $url . '?' . $request->getQueryString() : $url;
  7374. }
  7375. protected function collectGarbage(SessionInterface $session)
  7376. {
  7377. $config = $this->manager->getSessionConfig();
  7378. if ($this->configHitsLottery($config)) {
  7379. $session->getHandler()->gc($this->getLifetimeSeconds());
  7380. }
  7381. }
  7382. protected function configHitsLottery(array $config)
  7383. {
  7384. return mt_rand(1, $config['lottery'][1]) <= $config['lottery'][0];
  7385. }
  7386. protected function addCookieToResponse(Response $response, SessionInterface $session)
  7387. {
  7388. $s = $session;
  7389. if ($this->sessionIsPersistent($c = $this->manager->getSessionConfig())) {
  7390. $secure = array_get($c, 'secure', false);
  7391. $response->headers->setCookie(new Cookie($s->getName(), $s->getId(), $this->getCookieLifetime(), $c['path'], $c['domain'], $secure));
  7392. }
  7393. }
  7394. protected function getLifetimeSeconds()
  7395. {
  7396. return array_get($this->manager->getSessionConfig(), 'lifetime') * 60;
  7397. }
  7398. protected function getCookieLifetime()
  7399. {
  7400. $config = $this->manager->getSessionConfig();
  7401. return $config['expire_on_close'] ? 0 : Carbon::now()->addMinutes($config['lifetime']);
  7402. }
  7403. protected function sessionConfigured()
  7404. {
  7405. return !is_null(array_get($this->manager->getSessionConfig(), 'driver'));
  7406. }
  7407. protected function sessionIsPersistent(array $config = null)
  7408. {
  7409. $config = $config ?: $this->manager->getSessionConfig();
  7410. return !in_array($config['driver'], array(null, 'array'));
  7411. }
  7412. public function getSession(Request $request)
  7413. {
  7414. $session = $this->manager->driver();
  7415. $session->setId($request->cookies->get($session->getName()));
  7416. return $session;
  7417. }
  7418. }
  7419. namespace Illuminate\Session;
  7420. use SessionHandlerInterface;
  7421. use Symfony\Component\HttpFoundation\Request;
  7422. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  7423. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  7424. class Store implements SessionInterface
  7425. {
  7426. protected $id;
  7427. protected $name;
  7428. protected $attributes = array();
  7429. protected $bags = array();
  7430. protected $metaBag;
  7431. protected $bagData = array();
  7432. protected $handler;
  7433. protected $started = false;
  7434. public function __construct($name, SessionHandlerInterface $handler, $id = null)
  7435. {
  7436. $this->name = $name;
  7437. $this->handler = $handler;
  7438. $this->metaBag = new MetadataBag();
  7439. $this->setId($id ?: $this->generateSessionId());
  7440. }
  7441. public function start()
  7442. {
  7443. $this->loadSession();
  7444. if (!$this->has('_token')) {
  7445. $this->regenerateToken();
  7446. }
  7447. return $this->started = true;
  7448. }
  7449. protected function loadSession()
  7450. {
  7451. $this->attributes = $this->readFromHandler();
  7452. foreach (array_merge($this->bags, array($this->metaBag)) as $bag) {
  7453. $this->initializeLocalBag($bag);
  7454. $bag->initialize($this->bagData[$bag->getStorageKey()]);
  7455. }
  7456. }
  7457. protected function readFromHandler()
  7458. {
  7459. $data = $this->handler->read($this->getId());
  7460. return $data ? unserialize($data) : array();
  7461. }
  7462. protected function initializeLocalBag($bag)
  7463. {
  7464. $this->bagData[$bag->getStorageKey()] = $this->get($bag->getStorageKey(), array());
  7465. $this->forget($bag->getStorageKey());
  7466. }
  7467. public function getId()
  7468. {
  7469. return $this->id;
  7470. }
  7471. public function setId($id)
  7472. {
  7473. $this->id = $id ?: $this->generateSessionId();
  7474. }
  7475. protected function generateSessionId()
  7476. {
  7477. return sha1(uniqid('', true) . str_random(25) . microtime(true));
  7478. }
  7479. public function getName()
  7480. {
  7481. return $this->name;
  7482. }
  7483. public function setName($name)
  7484. {
  7485. $this->name = $name;
  7486. }
  7487. public function invalidate($lifetime = null)
  7488. {
  7489. $this->attributes = array();
  7490. $this->migrate();
  7491. return true;
  7492. }
  7493. public function migrate($destroy = false, $lifetime = null)
  7494. {
  7495. if ($destroy) {
  7496. $this->handler->destroy($this->getId());
  7497. }
  7498. $this->setExists(false);
  7499. $this->id = $this->generateSessionId();
  7500. return true;
  7501. }
  7502. public function regenerate($destroy = false)
  7503. {
  7504. return $this->migrate($destroy);
  7505. }
  7506. public function save()
  7507. {
  7508. $this->addBagDataToSession();
  7509. $this->ageFlashData();
  7510. $this->handler->write($this->getId(), serialize($this->attributes));
  7511. $this->started = false;
  7512. }
  7513. protected function addBagDataToSession()
  7514. {
  7515. foreach (array_merge($this->bags, array($this->metaBag)) as $bag) {
  7516. $this->put($bag->getStorageKey(), $this->bagData[$bag->getStorageKey()]);
  7517. }
  7518. }
  7519. public function ageFlashData()
  7520. {
  7521. foreach ($this->get('flash.old', array()) as $old) {
  7522. $this->forget($old);
  7523. }
  7524. $this->put('flash.old', $this->get('flash.new', array()));
  7525. $this->put('flash.new', array());
  7526. }
  7527. public function has($name)
  7528. {
  7529. return !is_null($this->get($name));
  7530. }
  7531. public function get($name, $default = null)
  7532. {
  7533. return array_get($this->attributes, $name, $default);
  7534. }
  7535. public function pull($key, $default = null)
  7536. {
  7537. $value = $this->get($key, $default);
  7538. $this->forget($key);
  7539. return $value;
  7540. }
  7541. public function hasOldInput($key = null)
  7542. {
  7543. $old = $this->getOldInput($key);
  7544. return is_null($key) ? count($old) > 0 : !is_null($old);
  7545. }
  7546. public function getOldInput($key = null, $default = null)
  7547. {
  7548. $input = $this->get('_old_input', array());
  7549. if (is_null($key)) {
  7550. return $input;
  7551. }
  7552. return array_get($input, $key, $default);
  7553. }
  7554. public function set($name, $value)
  7555. {
  7556. array_set($this->attributes, $name, $value);
  7557. }
  7558. public function put($key, $value)
  7559. {
  7560. if (!is_array($key)) {
  7561. $key = array($key => $value);
  7562. }
  7563. foreach ($key as $arrayKey => $arrayValue) {
  7564. $this->set($arrayKey, $arrayValue);
  7565. }
  7566. }
  7567. public function push($key, $value)
  7568. {
  7569. $array = $this->get($key, array());
  7570. $array[] = $value;
  7571. $this->put($key, $array);
  7572. }
  7573. public function flash($key, $value)
  7574. {
  7575. $this->put($key, $value);
  7576. $this->push('flash.new', $key);
  7577. $this->removeFromOldFlashData(array($key));
  7578. }
  7579. public function flashInput(array $value)
  7580. {
  7581. $this->flash('_old_input', $value);
  7582. }
  7583. public function reflash()
  7584. {
  7585. $this->mergeNewFlashes($this->get('flash.old', array()));
  7586. $this->put('flash.old', array());
  7587. }
  7588. public function keep($keys = null)
  7589. {
  7590. $keys = is_array($keys) ? $keys : func_get_args();
  7591. $this->mergeNewFlashes($keys);
  7592. $this->removeFromOldFlashData($keys);
  7593. }
  7594. protected function mergeNewFlashes(array $keys)
  7595. {
  7596. $values = array_unique(array_merge($this->get('flash.new', array()), $keys));
  7597. $this->put('flash.new', $values);
  7598. }
  7599. protected function removeFromOldFlashData(array $keys)
  7600. {
  7601. $this->put('flash.old', array_diff($this->get('flash.old', array()), $keys));
  7602. }
  7603. public function all()
  7604. {
  7605. return $this->attributes;
  7606. }
  7607. public function replace(array $attributes)
  7608. {
  7609. foreach ($attributes as $key => $value) {
  7610. $this->put($key, $value);
  7611. }
  7612. }
  7613. public function remove($name)
  7614. {
  7615. return array_pull($this->attributes, $name);
  7616. }
  7617. public function forget($key)
  7618. {
  7619. array_forget($this->attributes, $key);
  7620. }
  7621. public function clear()
  7622. {
  7623. $this->attributes = array();
  7624. foreach ($this->bags as $bag) {
  7625. $bag->clear();
  7626. }
  7627. }
  7628. public function flush()
  7629. {
  7630. $this->clear();
  7631. }
  7632. public function isStarted()
  7633. {
  7634. return $this->started;
  7635. }
  7636. public function registerBag(SessionBagInterface $bag)
  7637. {
  7638. $this->bags[$bag->getStorageKey()] = $bag;
  7639. }
  7640. public function getBag($name)
  7641. {
  7642. return array_get($this->bags, $name, function () {
  7643. throw new \InvalidArgumentException('Bag not registered.');
  7644. });
  7645. }
  7646. public function getMetadataBag()
  7647. {
  7648. return $this->metaBag;
  7649. }
  7650. public function getBagData($name)
  7651. {
  7652. return array_get($this->bagData, $name, array());
  7653. }
  7654. public function token()
  7655. {
  7656. return $this->get('_token');
  7657. }
  7658. public function getToken()
  7659. {
  7660. return $this->token();
  7661. }
  7662. public function regenerateToken()
  7663. {
  7664. $this->put('_token', str_random(40));
  7665. }
  7666. public function setExists($value)
  7667. {
  7668. if ($this->handler instanceof ExistenceAwareInterface) {
  7669. $this->handler->setExists($value);
  7670. }
  7671. }
  7672. public function getHandler()
  7673. {
  7674. return $this->handler;
  7675. }
  7676. public function handlerNeedsRequest()
  7677. {
  7678. return $this->handler instanceof CookieSessionHandler;
  7679. }
  7680. public function setRequestOnHandler(Request $request)
  7681. {
  7682. if ($this->handlerNeedsRequest()) {
  7683. $this->handler->setRequest($request);
  7684. }
  7685. }
  7686. }
  7687. namespace Illuminate\Session;
  7688. use Illuminate\Support\Manager;
  7689. use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
  7690. use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler;
  7691. class SessionManager extends Manager
  7692. {
  7693. protected function callCustomCreator($driver)
  7694. {
  7695. return $this->buildSession(parent::callCustomCreator($driver));
  7696. }
  7697. protected function createArrayDriver()
  7698. {
  7699. return new Store($this->app['config']['session.cookie'], new NullSessionHandler());
  7700. }
  7701. protected function createCookieDriver()
  7702. {
  7703. $lifetime = $this->app['config']['session.lifetime'];
  7704. return $this->buildSession(new CookieSessionHandler($this->app['cookie'], $lifetime));
  7705. }
  7706. protected function createFileDriver()
  7707. {
  7708. return $this->createNativeDriver();
  7709. }
  7710. protected function createNativeDriver()
  7711. {
  7712. $path = $this->app['config']['session.files'];
  7713. return $this->buildSession(new FileSessionHandler($this->app['files'], $path));
  7714. }
  7715. protected function createDatabaseDriver()
  7716. {
  7717. $connection = $this->getDatabaseConnection();
  7718. $table = $this->app['config']['session.table'];
  7719. return $this->buildSession(new DatabaseSessionHandler($connection, $table));
  7720. }
  7721. protected function getDatabaseConnection()
  7722. {
  7723. $connection = $this->app['config']['session.connection'];
  7724. return $this->app['db']->connection($connection);
  7725. }
  7726. protected function createApcDriver()
  7727. {
  7728. return $this->createCacheBased('apc');
  7729. }
  7730. protected function createMemcachedDriver()
  7731. {
  7732. return $this->createCacheBased('memcached');
  7733. }
  7734. protected function createWincacheDriver()
  7735. {
  7736. return $this->createCacheBased('wincache');
  7737. }
  7738. protected function createRedisDriver()
  7739. {
  7740. $handler = $this->createCacheHandler('redis');
  7741. $handler->getCache()->getStore()->setConnection($this->app['config']['session.connection']);
  7742. return $this->buildSession($handler);
  7743. }
  7744. protected function createCacheBased($driver)
  7745. {
  7746. return $this->buildSession($this->createCacheHandler($driver));
  7747. }
  7748. protected function createCacheHandler($driver)
  7749. {
  7750. $minutes = $this->app['config']['session.lifetime'];
  7751. return new CacheBasedSessionHandler($this->app['cache']->driver($driver), $minutes);
  7752. }
  7753. protected function buildSession($handler)
  7754. {
  7755. return new Store($this->app['config']['session.cookie'], $handler);
  7756. }
  7757. public function getSessionConfig()
  7758. {
  7759. return $this->app['config']['session'];
  7760. }
  7761. public function getDefaultDriver()
  7762. {
  7763. return $this->app['config']['session.driver'];
  7764. }
  7765. public function setDefaultDriver($name)
  7766. {
  7767. $this->app['config']['session.driver'] = $name;
  7768. }
  7769. }
  7770. namespace Illuminate\Support;
  7771. use Closure;
  7772. abstract class Manager
  7773. {
  7774. protected $app;
  7775. protected $customCreators = array();
  7776. protected $drivers = array();
  7777. public function __construct($app)
  7778. {
  7779. $this->app = $app;
  7780. }
  7781. public abstract function getDefaultDriver();
  7782. public function driver($driver = null)
  7783. {
  7784. $driver = $driver ?: $this->getDefaultDriver();
  7785. if (!isset($this->drivers[$driver])) {
  7786. $this->drivers[$driver] = $this->createDriver($driver);
  7787. }
  7788. return $this->drivers[$driver];
  7789. }
  7790. protected function createDriver($driver)
  7791. {
  7792. $method = 'create' . ucfirst($driver) . 'Driver';
  7793. if (isset($this->customCreators[$driver])) {
  7794. return $this->callCustomCreator($driver);
  7795. } elseif (method_exists($this, $method)) {
  7796. return $this->{$method}();
  7797. }
  7798. throw new \InvalidArgumentException("Driver [{$driver}] not supported.");
  7799. }
  7800. protected function callCustomCreator($driver)
  7801. {
  7802. return $this->customCreators[$driver]($this->app);
  7803. }
  7804. public function extend($driver, Closure $callback)
  7805. {
  7806. $this->customCreators[$driver] = $callback;
  7807. return $this;
  7808. }
  7809. public function getDrivers()
  7810. {
  7811. return $this->drivers;
  7812. }
  7813. public function __call($method, $parameters)
  7814. {
  7815. return call_user_func_array(array($this->driver(), $method), $parameters);
  7816. }
  7817. }
  7818. namespace Illuminate\Cookie;
  7819. use Symfony\Component\HttpFoundation\Cookie;
  7820. class CookieJar
  7821. {
  7822. protected $path = '/';
  7823. protected $domain = null;
  7824. protected $queued = array();
  7825. public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true)
  7826. {
  7827. list($path, $domain) = $this->getPathAndDomain($path, $domain);
  7828. $time = $minutes == 0 ? 0 : time() + $minutes * 60;
  7829. return new Cookie($name, $value, $time, $path, $domain, $secure, $httpOnly);
  7830. }
  7831. public function forever($name, $value, $path = null, $domain = null, $secure = false, $httpOnly = true)
  7832. {
  7833. return $this->make($name, $value, 2628000, $path, $domain, $secure, $httpOnly);
  7834. }
  7835. public function forget($name, $path = null, $domain = null)
  7836. {
  7837. return $this->make($name, null, -2628000, $path, $domain);
  7838. }
  7839. public function hasQueued($key)
  7840. {
  7841. return !is_null($this->queued($key));
  7842. }
  7843. public function queued($key, $default = null)
  7844. {
  7845. return array_get($this->queued, $key, $default);
  7846. }
  7847. public function queue()
  7848. {
  7849. if (head(func_get_args()) instanceof Cookie) {
  7850. $cookie = head(func_get_args());
  7851. } else {
  7852. $cookie = call_user_func_array(array($this, 'make'), func_get_args());
  7853. }
  7854. $this->queued[$cookie->getName()] = $cookie;
  7855. }
  7856. public function unqueue($name)
  7857. {
  7858. unset($this->queued[$name]);
  7859. }
  7860. protected function getPathAndDomain($path, $domain)
  7861. {
  7862. return array($path ?: $this->path, $domain ?: $this->domain);
  7863. }
  7864. public function setDefaultPathAndDomain($path, $domain)
  7865. {
  7866. list($this->path, $this->domain) = array($path, $domain);
  7867. return $this;
  7868. }
  7869. public function getQueuedCookies()
  7870. {
  7871. return $this->queued;
  7872. }
  7873. }
  7874. namespace Illuminate\Cookie;
  7875. use Illuminate\Encryption\Encrypter;
  7876. use Illuminate\Encryption\DecryptException;
  7877. use Symfony\Component\HttpFoundation\Cookie;
  7878. use Symfony\Component\HttpFoundation\Request;
  7879. use Symfony\Component\HttpFoundation\Response;
  7880. use Symfony\Component\HttpKernel\HttpKernelInterface;
  7881. class Guard implements HttpKernelInterface
  7882. {
  7883. protected $app;
  7884. protected $encrypter;
  7885. public function __construct(HttpKernelInterface $app, Encrypter $encrypter)
  7886. {
  7887. $this->app = $app;
  7888. $this->encrypter = $encrypter;
  7889. }
  7890. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  7891. {
  7892. return $this->encrypt($this->app->handle($this->decrypt($request), $type, $catch));
  7893. }
  7894. protected function decrypt(Request $request)
  7895. {
  7896. foreach ($request->cookies as $key => $c) {
  7897. try {
  7898. $request->cookies->set($key, $this->decryptCookie($c));
  7899. } catch (DecryptException $e) {
  7900. $request->cookies->set($key, null);
  7901. }
  7902. }
  7903. return $request;
  7904. }
  7905. protected function decryptCookie($cookie)
  7906. {
  7907. return is_array($cookie) ? $this->decryptArray($cookie) : $this->encrypter->decrypt($cookie);
  7908. }
  7909. protected function decryptArray(array $cookie)
  7910. {
  7911. $decrypted = array();
  7912. foreach ($cookie as $key => $value) {
  7913. $decrypted[$key] = $this->encrypter->decrypt($value);
  7914. }
  7915. return $decrypted;
  7916. }
  7917. protected function encrypt(Response $response)
  7918. {
  7919. foreach ($response->headers->getCookies() as $key => $c) {
  7920. $encrypted = $this->encrypter->encrypt($c->getValue());
  7921. $response->headers->setCookie($this->duplicate($c, $encrypted));
  7922. }
  7923. return $response;
  7924. }
  7925. protected function duplicate(Cookie $c, $value)
  7926. {
  7927. return new Cookie($c->getName(), $value, $c->getExpiresTime(), $c->getPath(), $c->getDomain(), $c->isSecure(), $c->isHttpOnly());
  7928. }
  7929. }
  7930. namespace Illuminate\Cookie;
  7931. use Symfony\Component\HttpFoundation\Request;
  7932. use Symfony\Component\HttpKernel\HttpKernelInterface;
  7933. class Queue implements HttpKernelInterface
  7934. {
  7935. protected $app;
  7936. protected $cookies;
  7937. public function __construct(HttpKernelInterface $app, CookieJar $cookies)
  7938. {
  7939. $this->app = $app;
  7940. $this->cookies = $cookies;
  7941. }
  7942. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  7943. {
  7944. $response = $this->app->handle($request, $type, $catch);
  7945. foreach ($this->cookies->getQueuedCookies() as $cookie) {
  7946. $response->headers->setCookie($cookie);
  7947. }
  7948. return $response;
  7949. }
  7950. }
  7951. namespace Illuminate\Encryption;
  7952. use Symfony\Component\Security\Core\Util\StringUtils;
  7953. use Symfony\Component\Security\Core\Util\SecureRandom;
  7954. class DecryptException extends \RuntimeException
  7955. {
  7956. }
  7957. class Encrypter
  7958. {
  7959. protected $key;
  7960. protected $cipher = MCRYPT_RIJNDAEL_128;
  7961. protected $mode = MCRYPT_MODE_CBC;
  7962. protected $block = 16;
  7963. public function __construct($key)
  7964. {
  7965. $this->key = $key;
  7966. }
  7967. public function encrypt($value)
  7968. {
  7969. $iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
  7970. $value = base64_encode($this->padAndMcrypt($value, $iv));
  7971. $mac = $this->hash($iv = base64_encode($iv), $value);
  7972. return base64_encode(json_encode(compact('iv', 'value', 'mac')));
  7973. }
  7974. protected function padAndMcrypt($value, $iv)
  7975. {
  7976. $value = $this->addPadding(serialize($value));
  7977. return mcrypt_encrypt($this->cipher, $this->key, $value, $this->mode, $iv);
  7978. }
  7979. public function decrypt($payload)
  7980. {
  7981. $payload = $this->getJsonPayload($payload);
  7982. $value = base64_decode($payload['value']);
  7983. $iv = base64_decode($payload['iv']);
  7984. return unserialize($this->stripPadding($this->mcryptDecrypt($value, $iv)));
  7985. }
  7986. protected function mcryptDecrypt($value, $iv)
  7987. {
  7988. try {
  7989. return mcrypt_decrypt($this->cipher, $this->key, $value, $this->mode, $iv);
  7990. } catch (\Exception $e) {
  7991. throw new DecryptException($e->getMessage());
  7992. }
  7993. }
  7994. protected function getJsonPayload($payload)
  7995. {
  7996. $payload = json_decode(base64_decode($payload), true);
  7997. if (!$payload || $this->invalidPayload($payload)) {
  7998. throw new DecryptException('Invalid data.');
  7999. }
  8000. if (!$this->validMac($payload)) {
  8001. throw new DecryptException('MAC is invalid.');
  8002. }
  8003. return $payload;
  8004. }
  8005. protected function validMac(array $payload)
  8006. {
  8007. $bytes = with(new SecureRandom())->nextBytes(16);
  8008. $calcMac = hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true);
  8009. return StringUtils::equals(hash_hmac('sha256', $payload['mac'], $bytes, true), $calcMac);
  8010. }
  8011. protected function hash($iv, $value)
  8012. {
  8013. return hash_hmac('sha256', $iv . $value, $this->key);
  8014. }
  8015. protected function addPadding($value)
  8016. {
  8017. $pad = $this->block - strlen($value) % $this->block;
  8018. return $value . str_repeat(chr($pad), $pad);
  8019. }
  8020. protected function stripPadding($value)
  8021. {
  8022. $pad = ord($value[($len = strlen($value)) - 1]);
  8023. return $this->paddingIsValid($pad, $value) ? substr($value, 0, $len - $pad) : $value;
  8024. }
  8025. protected function paddingIsValid($pad, $value)
  8026. {
  8027. $beforePad = strlen($value) - $pad;
  8028. return substr($value, $beforePad) == str_repeat(substr($value, -1), $pad);
  8029. }
  8030. protected function invalidPayload($data)
  8031. {
  8032. return !is_array($data) || !isset($data['iv']) || !isset($data['value']) || !isset($data['mac']);
  8033. }
  8034. protected function getIvSize()
  8035. {
  8036. return mcrypt_get_iv_size($this->cipher, $this->mode);
  8037. }
  8038. protected function getRandomizer()
  8039. {
  8040. if (defined('MCRYPT_DEV_URANDOM')) {
  8041. return MCRYPT_DEV_URANDOM;
  8042. }
  8043. if (defined('MCRYPT_DEV_RANDOM')) {
  8044. return MCRYPT_DEV_RANDOM;
  8045. }
  8046. mt_srand();
  8047. return MCRYPT_RAND;
  8048. }
  8049. public function setKey($key)
  8050. {
  8051. $this->key = $key;
  8052. }
  8053. public function setCipher($cipher)
  8054. {
  8055. $this->cipher = $cipher;
  8056. $this->updateBlockSize();
  8057. }
  8058. public function setMode($mode)
  8059. {
  8060. $this->mode = $mode;
  8061. $this->updateBlockSize();
  8062. }
  8063. protected function updateBlockSize()
  8064. {
  8065. $this->block = mcrypt_get_iv_size($this->cipher, $this->mode);
  8066. }
  8067. }
  8068. namespace Illuminate\Support\Facades;
  8069. class Log extends Facade
  8070. {
  8071. protected static function getFacadeAccessor()
  8072. {
  8073. return 'log';
  8074. }
  8075. }
  8076. namespace Illuminate\Log;
  8077. use Monolog\Logger;
  8078. use Illuminate\Support\ServiceProvider;
  8079. class LogServiceProvider extends ServiceProvider
  8080. {
  8081. protected $defer = true;
  8082. public function register()
  8083. {
  8084. $logger = new Writer(new Logger($this->app['env']), $this->app['events']);
  8085. $this->app->instance('log', $logger);
  8086. if (isset($this->app['log.setup'])) {
  8087. call_user_func($this->app['log.setup'], $logger);
  8088. }
  8089. }
  8090. public function provides()
  8091. {
  8092. return array('log');
  8093. }
  8094. }
  8095. namespace Illuminate\Log;
  8096. use Closure;
  8097. use Illuminate\Events\Dispatcher;
  8098. use Monolog\Handler\StreamHandler;
  8099. use Monolog\Logger as MonologLogger;
  8100. use Monolog\Formatter\LineFormatter;
  8101. use Monolog\Handler\ErrorLogHandler;
  8102. use Monolog\Handler\RotatingFileHandler;
  8103. use Illuminate\Support\Contracts\JsonableInterface;
  8104. use Illuminate\Support\Contracts\ArrayableInterface;
  8105. class Writer
  8106. {
  8107. protected $monolog;
  8108. protected $levels = array('debug', 'info', 'notice', 'warning', 'error', 'critical', 'alert', 'emergency');
  8109. protected $dispatcher;
  8110. public function __construct(MonologLogger $monolog, Dispatcher $dispatcher = null)
  8111. {
  8112. $this->monolog = $monolog;
  8113. if (isset($dispatcher)) {
  8114. $this->dispatcher = $dispatcher;
  8115. }
  8116. }
  8117. protected function callMonolog($method, $parameters)
  8118. {
  8119. if (is_array($parameters[0])) {
  8120. $parameters[0] = json_encode($parameters[0]);
  8121. }
  8122. return call_user_func_array(array($this->monolog, $method), $parameters);
  8123. }
  8124. public function useFiles($path, $level = 'debug')
  8125. {
  8126. $level = $this->parseLevel($level);
  8127. $this->monolog->pushHandler($handler = new StreamHandler($path, $level));
  8128. $handler->setFormatter($this->getDefaultFormatter());
  8129. }
  8130. public function useDailyFiles($path, $days = 0, $level = 'debug')
  8131. {
  8132. $level = $this->parseLevel($level);
  8133. $this->monolog->pushHandler($handler = new RotatingFileHandler($path, $days, $level));
  8134. $handler->setFormatter($this->getDefaultFormatter());
  8135. }
  8136. public function useErrorLog($level = 'debug', $messageType = ErrorLogHandler::OPERATING_SYSTEM)
  8137. {
  8138. $level = $this->parseLevel($level);
  8139. $this->monolog->pushHandler($handler = new ErrorLogHandler($messageType, $level));
  8140. $handler->setFormatter($this->getDefaultFormatter());
  8141. }
  8142. protected function getDefaultFormatter()
  8143. {
  8144. return new LineFormatter(null, null, true);
  8145. }
  8146. protected function parseLevel($level)
  8147. {
  8148. switch ($level) {
  8149. case 'debug':
  8150. return MonologLogger::DEBUG;
  8151. case 'info':
  8152. return MonologLogger::INFO;
  8153. case 'notice':
  8154. return MonologLogger::NOTICE;
  8155. case 'warning':
  8156. return MonologLogger::WARNING;
  8157. case 'error':
  8158. return MonologLogger::ERROR;
  8159. case 'critical':
  8160. return MonologLogger::CRITICAL;
  8161. case 'alert':
  8162. return MonologLogger::ALERT;
  8163. case 'emergency':
  8164. return MonologLogger::EMERGENCY;
  8165. default:
  8166. throw new \InvalidArgumentException('Invalid log level.');
  8167. }
  8168. }
  8169. public function listen(Closure $callback)
  8170. {
  8171. if (!isset($this->dispatcher)) {
  8172. throw new \RuntimeException('Events dispatcher has not been set.');
  8173. }
  8174. $this->dispatcher->listen('illuminate.log', $callback);
  8175. }
  8176. public function getMonolog()
  8177. {
  8178. return $this->monolog;
  8179. }
  8180. public function getEventDispatcher()
  8181. {
  8182. return $this->dispatcher;
  8183. }
  8184. public function setEventDispatcher(Dispatcher $dispatcher)
  8185. {
  8186. $this->dispatcher = $dispatcher;
  8187. }
  8188. protected function fireLogEvent($level, $message, array $context = array())
  8189. {
  8190. if (isset($this->dispatcher)) {
  8191. $this->dispatcher->fire('illuminate.log', compact('level', 'message', 'context'));
  8192. }
  8193. }
  8194. public function write()
  8195. {
  8196. $level = head(func_get_args());
  8197. return call_user_func_array(array($this, $level), array_slice(func_get_args(), 1));
  8198. }
  8199. public function __call($method, $parameters)
  8200. {
  8201. $this->formatParameters($parameters);
  8202. if (in_array($method, $this->levels)) {
  8203. call_user_func_array(array($this, 'fireLogEvent'), array_merge(array($method), $parameters));
  8204. $method = 'add' . ucfirst($method);
  8205. return $this->callMonolog($method, $parameters);
  8206. }
  8207. throw new \BadMethodCallException("Method [{$method}] does not exist.");
  8208. }
  8209. protected function formatParameters(&$parameters)
  8210. {
  8211. if (isset($parameters[0])) {
  8212. if (is_array($parameters[0])) {
  8213. $parameters[0] = var_export($parameters[0], true);
  8214. } elseif ($parameters[0] instanceof JsonableInterface) {
  8215. $parameters[0] = $parameters[0]->toJson();
  8216. } elseif ($parameters[0] instanceof ArrayableInterface) {
  8217. $parameters[0] = var_export($parameters[0]->toArray(), true);
  8218. }
  8219. }
  8220. }
  8221. }
  8222. namespace Monolog;
  8223. use Monolog\Handler\HandlerInterface;
  8224. use Monolog\Handler\StreamHandler;
  8225. use Psr\Log\LoggerInterface;
  8226. use Psr\Log\InvalidArgumentException;
  8227. class Logger implements LoggerInterface
  8228. {
  8229. const DEBUG = 100;
  8230. const INFO = 200;
  8231. const NOTICE = 250;
  8232. const WARNING = 300;
  8233. const ERROR = 400;
  8234. const CRITICAL = 500;
  8235. const ALERT = 550;
  8236. const EMERGENCY = 600;
  8237. const API = 1;
  8238. protected static $levels = array(100 => 'DEBUG', 200 => 'INFO', 250 => 'NOTICE', 300 => 'WARNING', 400 => 'ERROR', 500 => 'CRITICAL', 550 => 'ALERT', 600 => 'EMERGENCY');
  8239. protected static $timezone;
  8240. protected $name;
  8241. protected $handlers;
  8242. protected $processors;
  8243. public function __construct($name, array $handlers = array(), array $processors = array())
  8244. {
  8245. $this->name = $name;
  8246. $this->handlers = $handlers;
  8247. $this->processors = $processors;
  8248. }
  8249. public function getName()
  8250. {
  8251. return $this->name;
  8252. }
  8253. public function pushHandler(HandlerInterface $handler)
  8254. {
  8255. array_unshift($this->handlers, $handler);
  8256. }
  8257. public function popHandler()
  8258. {
  8259. if (!$this->handlers) {
  8260. throw new \LogicException('You tried to pop from an empty handler stack.');
  8261. }
  8262. return array_shift($this->handlers);
  8263. }
  8264. public function getHandlers()
  8265. {
  8266. return $this->handlers;
  8267. }
  8268. public function pushProcessor($callback)
  8269. {
  8270. if (!is_callable($callback)) {
  8271. throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . var_export($callback, true) . ' given');
  8272. }
  8273. array_unshift($this->processors, $callback);
  8274. }
  8275. public function popProcessor()
  8276. {
  8277. if (!$this->processors) {
  8278. throw new \LogicException('You tried to pop from an empty processor stack.');
  8279. }
  8280. return array_shift($this->processors);
  8281. }
  8282. public function getProcessors()
  8283. {
  8284. return $this->processors;
  8285. }
  8286. public function addRecord($level, $message, array $context = array())
  8287. {
  8288. if (!$this->handlers) {
  8289. $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
  8290. }
  8291. if (!static::$timezone) {
  8292. static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC');
  8293. }
  8294. $record = array('message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => static::getLevelName($level), 'channel' => $this->name, 'datetime' => \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone), 'extra' => array());
  8295. $handlerKey = null;
  8296. foreach ($this->handlers as $key => $handler) {
  8297. if ($handler->isHandling($record)) {
  8298. $handlerKey = $key;
  8299. break;
  8300. }
  8301. }
  8302. if (null === $handlerKey) {
  8303. return false;
  8304. }
  8305. foreach ($this->processors as $processor) {
  8306. $record = call_user_func($processor, $record);
  8307. }
  8308. while (isset($this->handlers[$handlerKey]) && false === $this->handlers[$handlerKey]->handle($record)) {
  8309. $handlerKey++;
  8310. }
  8311. return true;
  8312. }
  8313. public function addDebug($message, array $context = array())
  8314. {
  8315. return $this->addRecord(static::DEBUG, $message, $context);
  8316. }
  8317. public function addInfo($message, array $context = array())
  8318. {
  8319. return $this->addRecord(static::INFO, $message, $context);
  8320. }
  8321. public function addNotice($message, array $context = array())
  8322. {
  8323. return $this->addRecord(static::NOTICE, $message, $context);
  8324. }
  8325. public function addWarning($message, array $context = array())
  8326. {
  8327. return $this->addRecord(static::WARNING, $message, $context);
  8328. }
  8329. public function addError($message, array $context = array())
  8330. {
  8331. return $this->addRecord(static::ERROR, $message, $context);
  8332. }
  8333. public function addCritical($message, array $context = array())
  8334. {
  8335. return $this->addRecord(static::CRITICAL, $message, $context);
  8336. }
  8337. public function addAlert($message, array $context = array())
  8338. {
  8339. return $this->addRecord(static::ALERT, $message, $context);
  8340. }
  8341. public function addEmergency($message, array $context = array())
  8342. {
  8343. return $this->addRecord(static::EMERGENCY, $message, $context);
  8344. }
  8345. public static function getLevels()
  8346. {
  8347. return array_flip(static::$levels);
  8348. }
  8349. public static function getLevelName($level)
  8350. {
  8351. if (!isset(static::$levels[$level])) {
  8352. throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels)));
  8353. }
  8354. return static::$levels[$level];
  8355. }
  8356. public function isHandling($level)
  8357. {
  8358. $record = array('level' => $level);
  8359. foreach ($this->handlers as $handler) {
  8360. if ($handler->isHandling($record)) {
  8361. return true;
  8362. }
  8363. }
  8364. return false;
  8365. }
  8366. public function log($level, $message, array $context = array())
  8367. {
  8368. if (is_string($level) && defined(__CLASS__ . '::' . strtoupper($level))) {
  8369. $level = constant(__CLASS__ . '::' . strtoupper($level));
  8370. }
  8371. return $this->addRecord($level, $message, $context);
  8372. }
  8373. public function debug($message, array $context = array())
  8374. {
  8375. return $this->addRecord(static::DEBUG, $message, $context);
  8376. }
  8377. public function info($message, array $context = array())
  8378. {
  8379. return $this->addRecord(static::INFO, $message, $context);
  8380. }
  8381. public function notice($message, array $context = array())
  8382. {
  8383. return $this->addRecord(static::NOTICE, $message, $context);
  8384. }
  8385. public function warn($message, array $context = array())
  8386. {
  8387. return $this->addRecord(static::WARNING, $message, $context);
  8388. }
  8389. public function warning($message, array $context = array())
  8390. {
  8391. return $this->addRecord(static::WARNING, $message, $context);
  8392. }
  8393. public function err($message, array $context = array())
  8394. {
  8395. return $this->addRecord(static::ERROR, $message, $context);
  8396. }
  8397. public function error($message, array $context = array())
  8398. {
  8399. return $this->addRecord(static::ERROR, $message, $context);
  8400. }
  8401. public function crit($message, array $context = array())
  8402. {
  8403. return $this->addRecord(static::CRITICAL, $message, $context);
  8404. }
  8405. public function critical($message, array $context = array())
  8406. {
  8407. return $this->addRecord(static::CRITICAL, $message, $context);
  8408. }
  8409. public function alert($message, array $context = array())
  8410. {
  8411. return $this->addRecord(static::ALERT, $message, $context);
  8412. }
  8413. public function emerg($message, array $context = array())
  8414. {
  8415. return $this->addRecord(static::EMERGENCY, $message, $context);
  8416. }
  8417. public function emergency($message, array $context = array())
  8418. {
  8419. return $this->addRecord(static::EMERGENCY, $message, $context);
  8420. }
  8421. }
  8422. namespace Psr\Log;
  8423. interface LoggerInterface
  8424. {
  8425. public function emergency($message, array $context = array());
  8426. public function alert($message, array $context = array());
  8427. public function critical($message, array $context = array());
  8428. public function error($message, array $context = array());
  8429. public function warning($message, array $context = array());
  8430. public function notice($message, array $context = array());
  8431. public function info($message, array $context = array());
  8432. public function debug($message, array $context = array());
  8433. public function log($level, $message, array $context = array());
  8434. }
  8435. namespace Monolog\Handler;
  8436. use Monolog\Logger;
  8437. use Monolog\Formatter\FormatterInterface;
  8438. use Monolog\Formatter\LineFormatter;
  8439. abstract class AbstractHandler implements HandlerInterface
  8440. {
  8441. protected $level = Logger::DEBUG;
  8442. protected $bubble = true;
  8443. protected $formatter;
  8444. protected $processors = array();
  8445. public function __construct($level = Logger::DEBUG, $bubble = true)
  8446. {
  8447. $this->level = $level;
  8448. $this->bubble = $bubble;
  8449. }
  8450. public function isHandling(array $record)
  8451. {
  8452. return $record['level'] >= $this->level;
  8453. }
  8454. public function handleBatch(array $records)
  8455. {
  8456. foreach ($records as $record) {
  8457. $this->handle($record);
  8458. }
  8459. }
  8460. public function close()
  8461. {
  8462. }
  8463. public function pushProcessor($callback)
  8464. {
  8465. if (!is_callable($callback)) {
  8466. throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), ' . var_export($callback, true) . ' given');
  8467. }
  8468. array_unshift($this->processors, $callback);
  8469. return $this;
  8470. }
  8471. public function popProcessor()
  8472. {
  8473. if (!$this->processors) {
  8474. throw new \LogicException('You tried to pop from an empty processor stack.');
  8475. }
  8476. return array_shift($this->processors);
  8477. }
  8478. public function setFormatter(FormatterInterface $formatter)
  8479. {
  8480. $this->formatter = $formatter;
  8481. return $this;
  8482. }
  8483. public function getFormatter()
  8484. {
  8485. if (!$this->formatter) {
  8486. $this->formatter = $this->getDefaultFormatter();
  8487. }
  8488. return $this->formatter;
  8489. }
  8490. public function setLevel($level)
  8491. {
  8492. $this->level = $level;
  8493. return $this;
  8494. }
  8495. public function getLevel()
  8496. {
  8497. return $this->level;
  8498. }
  8499. public function setBubble($bubble)
  8500. {
  8501. $this->bubble = $bubble;
  8502. return $this;
  8503. }
  8504. public function getBubble()
  8505. {
  8506. return $this->bubble;
  8507. }
  8508. public function __destruct()
  8509. {
  8510. try {
  8511. $this->close();
  8512. } catch (\Exception $e) {
  8513. }
  8514. }
  8515. protected function getDefaultFormatter()
  8516. {
  8517. return new LineFormatter();
  8518. }
  8519. }
  8520. namespace Monolog\Handler;
  8521. abstract class AbstractProcessingHandler extends AbstractHandler
  8522. {
  8523. public function handle(array $record)
  8524. {
  8525. if (!$this->isHandling($record)) {
  8526. return false;
  8527. }
  8528. $record = $this->processRecord($record);
  8529. $record['formatted'] = $this->getFormatter()->format($record);
  8530. $this->write($record);
  8531. return false === $this->bubble;
  8532. }
  8533. protected abstract function write(array $record);
  8534. protected function processRecord(array $record)
  8535. {
  8536. if ($this->processors) {
  8537. foreach ($this->processors as $processor) {
  8538. $record = call_user_func($processor, $record);
  8539. }
  8540. }
  8541. return $record;
  8542. }
  8543. }
  8544. namespace Monolog\Handler;
  8545. use Monolog\Logger;
  8546. class StreamHandler extends AbstractProcessingHandler
  8547. {
  8548. protected $stream;
  8549. protected $url;
  8550. private $errorMessage;
  8551. protected $filePermission;
  8552. public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null)
  8553. {
  8554. parent::__construct($level, $bubble);
  8555. if (is_resource($stream)) {
  8556. $this->stream = $stream;
  8557. } else {
  8558. $this->url = $stream;
  8559. }
  8560. $this->filePermission = $filePermission;
  8561. }
  8562. public function close()
  8563. {
  8564. if (is_resource($this->stream)) {
  8565. fclose($this->stream);
  8566. }
  8567. $this->stream = null;
  8568. }
  8569. protected function write(array $record)
  8570. {
  8571. if (!is_resource($this->stream)) {
  8572. if (!$this->url) {
  8573. throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
  8574. }
  8575. $this->errorMessage = null;
  8576. set_error_handler(array($this, 'customErrorHandler'));
  8577. $this->stream = fopen($this->url, 'a');
  8578. if ($this->filePermission !== null) {
  8579. @chmod($this->url, $this->filePermission);
  8580. }
  8581. restore_error_handler();
  8582. if (!is_resource($this->stream)) {
  8583. $this->stream = null;
  8584. throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $this->errorMessage, $this->url));
  8585. }
  8586. }
  8587. fwrite($this->stream, (string) $record['formatted']);
  8588. }
  8589. private function customErrorHandler($code, $msg)
  8590. {
  8591. $this->errorMessage = preg_replace('{^fopen\\(.*?\\): }', '', $msg);
  8592. }
  8593. }
  8594. namespace Monolog\Handler;
  8595. use Monolog\Logger;
  8596. class RotatingFileHandler extends StreamHandler
  8597. {
  8598. protected $filename;
  8599. protected $maxFiles;
  8600. protected $mustRotate;
  8601. protected $nextRotation;
  8602. protected $filenameFormat;
  8603. protected $dateFormat;
  8604. public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null)
  8605. {
  8606. $this->filename = $filename;
  8607. $this->maxFiles = (int) $maxFiles;
  8608. $this->nextRotation = new \DateTime('tomorrow');
  8609. $this->filenameFormat = '{filename}-{date}';
  8610. $this->dateFormat = 'Y-m-d';
  8611. parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission);
  8612. }
  8613. public function close()
  8614. {
  8615. parent::close();
  8616. if (true === $this->mustRotate) {
  8617. $this->rotate();
  8618. }
  8619. }
  8620. public function setFilenameFormat($filenameFormat, $dateFormat)
  8621. {
  8622. $this->filenameFormat = $filenameFormat;
  8623. $this->dateFormat = $dateFormat;
  8624. $this->url = $this->getTimedFilename();
  8625. $this->close();
  8626. }
  8627. protected function write(array $record)
  8628. {
  8629. if (null === $this->mustRotate) {
  8630. $this->mustRotate = !file_exists($this->url);
  8631. }
  8632. if ($this->nextRotation < $record['datetime']) {
  8633. $this->mustRotate = true;
  8634. $this->close();
  8635. }
  8636. parent::write($record);
  8637. }
  8638. protected function rotate()
  8639. {
  8640. $this->url = $this->getTimedFilename();
  8641. $this->nextRotation = new \DateTime('tomorrow');
  8642. if (0 === $this->maxFiles) {
  8643. return;
  8644. }
  8645. $logFiles = glob($this->getGlobPattern());
  8646. if ($this->maxFiles >= count($logFiles)) {
  8647. return;
  8648. }
  8649. usort($logFiles, function ($a, $b) {
  8650. return strcmp($b, $a);
  8651. });
  8652. foreach (array_slice($logFiles, $this->maxFiles) as $file) {
  8653. if (is_writable($file)) {
  8654. unlink($file);
  8655. }
  8656. }
  8657. }
  8658. protected function getTimedFilename()
  8659. {
  8660. $fileInfo = pathinfo($this->filename);
  8661. $timedFilename = str_replace(array('{filename}', '{date}'), array($fileInfo['filename'], date($this->dateFormat)), $fileInfo['dirname'] . '/' . $this->filenameFormat);
  8662. if (!empty($fileInfo['extension'])) {
  8663. $timedFilename .= '.' . $fileInfo['extension'];
  8664. }
  8665. return $timedFilename;
  8666. }
  8667. protected function getGlobPattern()
  8668. {
  8669. $fileInfo = pathinfo($this->filename);
  8670. $glob = str_replace(array('{filename}', '{date}'), array($fileInfo['filename'], '*'), $fileInfo['dirname'] . '/' . $this->filenameFormat);
  8671. if (!empty($fileInfo['extension'])) {
  8672. $glob .= '.' . $fileInfo['extension'];
  8673. }
  8674. return $glob;
  8675. }
  8676. }
  8677. namespace Monolog\Handler;
  8678. use Monolog\Formatter\FormatterInterface;
  8679. interface HandlerInterface
  8680. {
  8681. public function isHandling(array $record);
  8682. public function handle(array $record);
  8683. public function handleBatch(array $records);
  8684. public function pushProcessor($callback);
  8685. public function popProcessor();
  8686. public function setFormatter(FormatterInterface $formatter);
  8687. public function getFormatter();
  8688. }
  8689. namespace Illuminate\Support\Facades;
  8690. class App extends Facade
  8691. {
  8692. protected static function getFacadeAccessor()
  8693. {
  8694. return 'app';
  8695. }
  8696. }
  8697. namespace Illuminate\Exception;
  8698. use Exception;
  8699. interface ExceptionDisplayerInterface
  8700. {
  8701. public function display(Exception $exception);
  8702. }
  8703. namespace Illuminate\Exception;
  8704. use Exception;
  8705. use Symfony\Component\Debug\ExceptionHandler;
  8706. use Symfony\Component\HttpFoundation\JsonResponse;
  8707. class SymfonyDisplayer implements ExceptionDisplayerInterface
  8708. {
  8709. protected $symfony;
  8710. protected $returnJson;
  8711. public function __construct(ExceptionHandler $symfony, $returnJson = false)
  8712. {
  8713. $this->symfony = $symfony;
  8714. $this->returnJson = $returnJson;
  8715. }
  8716. public function display(Exception $exception)
  8717. {
  8718. if ($this->returnJson) {
  8719. return new JsonResponse(array('error' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine()), 500);
  8720. } else {
  8721. return $this->symfony->createResponse($exception);
  8722. }
  8723. }
  8724. }
  8725. namespace Illuminate\Exception;
  8726. use Exception;
  8727. use Whoops\Run;
  8728. use Symfony\Component\HttpFoundation\Response;
  8729. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  8730. class WhoopsDisplayer implements ExceptionDisplayerInterface
  8731. {
  8732. protected $whoops;
  8733. protected $runningInConsole;
  8734. public function __construct(Run $whoops, $runningInConsole)
  8735. {
  8736. $this->whoops = $whoops;
  8737. $this->runningInConsole = $runningInConsole;
  8738. }
  8739. public function display(Exception $exception)
  8740. {
  8741. $status = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500;
  8742. $headers = $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : array();
  8743. return new Response($this->whoops->handleException($exception), $status, $headers);
  8744. }
  8745. }
  8746. namespace Illuminate\Exception;
  8747. use Closure;
  8748. use ErrorException;
  8749. use ReflectionFunction;
  8750. use Illuminate\Support\Contracts\ResponsePreparerInterface;
  8751. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  8752. use Symfony\Component\Debug\Exception\FatalErrorException as FatalError;
  8753. class Handler
  8754. {
  8755. protected $responsePreparer;
  8756. protected $plainDisplayer;
  8757. protected $debugDisplayer;
  8758. protected $debug;
  8759. protected $handlers = array();
  8760. protected $handled = array();
  8761. public function __construct(ResponsePreparerInterface $responsePreparer, ExceptionDisplayerInterface $plainDisplayer, ExceptionDisplayerInterface $debugDisplayer, $debug = true)
  8762. {
  8763. $this->debug = $debug;
  8764. $this->plainDisplayer = $plainDisplayer;
  8765. $this->debugDisplayer = $debugDisplayer;
  8766. $this->responsePreparer = $responsePreparer;
  8767. }
  8768. public function register($environment)
  8769. {
  8770. $this->registerErrorHandler();
  8771. $this->registerExceptionHandler();
  8772. if ($environment != 'testing') {
  8773. $this->registerShutdownHandler();
  8774. }
  8775. }
  8776. protected function registerErrorHandler()
  8777. {
  8778. set_error_handler(array($this, 'handleError'));
  8779. }
  8780. protected function registerExceptionHandler()
  8781. {
  8782. set_exception_handler(array($this, 'handleUncaughtException'));
  8783. }
  8784. protected function registerShutdownHandler()
  8785. {
  8786. register_shutdown_function(array($this, 'handleShutdown'));
  8787. }
  8788. public function handleError($level, $message, $file = '', $line = 0, $context = array())
  8789. {
  8790. if (error_reporting() & $level) {
  8791. throw new ErrorException($message, 0, $level, $file, $line);
  8792. }
  8793. }
  8794. public function handleException($exception)
  8795. {
  8796. $response = $this->callCustomHandlers($exception);
  8797. if (!is_null($response)) {
  8798. return $this->prepareResponse($response);
  8799. }
  8800. return $this->displayException($exception);
  8801. }
  8802. public function handleUncaughtException($exception)
  8803. {
  8804. $this->handleException($exception)->send();
  8805. }
  8806. public function handleShutdown()
  8807. {
  8808. $error = error_get_last();
  8809. if (!is_null($error)) {
  8810. extract($error);
  8811. if (!$this->isFatal($type)) {
  8812. return;
  8813. }
  8814. $this->handleException(new FatalError($message, $type, 0, $file, $line))->send();
  8815. }
  8816. }
  8817. protected function isFatal($type)
  8818. {
  8819. return in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE));
  8820. }
  8821. public function handleConsole($exception)
  8822. {
  8823. return $this->callCustomHandlers($exception, true);
  8824. }
  8825. protected function callCustomHandlers($exception, $fromConsole = false)
  8826. {
  8827. foreach ($this->handlers as $handler) {
  8828. if (!$this->handlesException($handler, $exception)) {
  8829. continue;
  8830. } elseif ($exception instanceof HttpExceptionInterface) {
  8831. $code = $exception->getStatusCode();
  8832. } else {
  8833. $code = 500;
  8834. }
  8835. try {
  8836. $response = $handler($exception, $code, $fromConsole);
  8837. } catch (\Exception $e) {
  8838. $response = $this->formatException($e);
  8839. }
  8840. if (isset($response) && !is_null($response)) {
  8841. return $response;
  8842. }
  8843. }
  8844. }
  8845. protected function displayException($exception)
  8846. {
  8847. $displayer = $this->debug ? $this->debugDisplayer : $this->plainDisplayer;
  8848. return $displayer->display($exception);
  8849. }
  8850. protected function handlesException(Closure $handler, $exception)
  8851. {
  8852. $reflection = new ReflectionFunction($handler);
  8853. return $reflection->getNumberOfParameters() == 0 || $this->hints($reflection, $exception);
  8854. }
  8855. protected function hints(ReflectionFunction $reflection, $exception)
  8856. {
  8857. $parameters = $reflection->getParameters();
  8858. $expected = $parameters[0];
  8859. return !$expected->getClass() || $expected->getClass()->isInstance($exception);
  8860. }
  8861. protected function formatException(\Exception $e)
  8862. {
  8863. if ($this->debug) {
  8864. $location = $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine();
  8865. return 'Error in exception handler: ' . $location;
  8866. }
  8867. return 'Error in exception handler.';
  8868. }
  8869. public function error(Closure $callback)
  8870. {
  8871. array_unshift($this->handlers, $callback);
  8872. }
  8873. public function pushError(Closure $callback)
  8874. {
  8875. $this->handlers[] = $callback;
  8876. }
  8877. protected function prepareResponse($response)
  8878. {
  8879. return $this->responsePreparer->prepareResponse($response);
  8880. }
  8881. public function runningInConsole()
  8882. {
  8883. return php_sapi_name() == 'cli';
  8884. }
  8885. public function setDebug($debug)
  8886. {
  8887. $this->debug = $debug;
  8888. }
  8889. }
  8890. namespace Illuminate\Support\Facades;
  8891. class Route extends Facade
  8892. {
  8893. protected static function getFacadeAccessor()
  8894. {
  8895. return 'router';
  8896. }
  8897. }
  8898. namespace Illuminate\View\Engines;
  8899. use Closure;
  8900. class EngineResolver
  8901. {
  8902. protected $resolvers = array();
  8903. protected $resolved = array();
  8904. public function register($engine, Closure $resolver)
  8905. {
  8906. $this->resolvers[$engine] = $resolver;
  8907. }
  8908. public function resolve($engine)
  8909. {
  8910. if (isset($this->resolved[$engine])) {
  8911. return $this->resolved[$engine];
  8912. }
  8913. if (isset($this->resolvers[$engine])) {
  8914. return $this->resolved[$engine] = call_user_func($this->resolvers[$engine]);
  8915. }
  8916. throw new \InvalidArgumentException("Engine {$engine} not found.");
  8917. }
  8918. }
  8919. namespace Illuminate\View;
  8920. interface ViewFinderInterface
  8921. {
  8922. public function find($view);
  8923. public function addLocation($location);
  8924. public function addNamespace($namespace, $hints);
  8925. public function prependNamespace($namespace, $hints);
  8926. public function addExtension($extension);
  8927. }
  8928. namespace Illuminate\View;
  8929. use Illuminate\Filesystem\Filesystem;
  8930. class FileViewFinder implements ViewFinderInterface
  8931. {
  8932. protected $files;
  8933. protected $paths;
  8934. protected $views = array();
  8935. protected $hints = array();
  8936. protected $extensions = array('blade.php', 'php');
  8937. const HINT_PATH_DELIMITER = '::';
  8938. public function __construct(Filesystem $files, array $paths, array $extensions = null)
  8939. {
  8940. $this->files = $files;
  8941. $this->paths = $paths;
  8942. if (isset($extensions)) {
  8943. $this->extensions = $extensions;
  8944. }
  8945. }
  8946. public function find($name)
  8947. {
  8948. if (isset($this->views[$name])) {
  8949. return $this->views[$name];
  8950. }
  8951. if ($this->hasHintInformation($name = trim($name))) {
  8952. return $this->views[$name] = $this->findNamedPathView($name);
  8953. }
  8954. return $this->views[$name] = $this->findInPaths($name, $this->paths);
  8955. }
  8956. protected function findNamedPathView($name)
  8957. {
  8958. list($namespace, $view) = $this->getNamespaceSegments($name);
  8959. return $this->findInPaths($view, $this->hints[$namespace]);
  8960. }
  8961. protected function getNamespaceSegments($name)
  8962. {
  8963. $segments = explode(static::HINT_PATH_DELIMITER, $name);
  8964. if (count($segments) != 2) {
  8965. throw new \InvalidArgumentException("View [{$name}] has an invalid name.");
  8966. }
  8967. if (!isset($this->hints[$segments[0]])) {
  8968. throw new \InvalidArgumentException("No hint path defined for [{$segments[0]}].");
  8969. }
  8970. return $segments;
  8971. }
  8972. protected function findInPaths($name, $paths)
  8973. {
  8974. foreach ((array) $paths as $path) {
  8975. foreach ($this->getPossibleViewFiles($name) as $file) {
  8976. if ($this->files->exists($viewPath = $path . '/' . $file)) {
  8977. return $viewPath;
  8978. }
  8979. }
  8980. }
  8981. throw new \InvalidArgumentException("View [{$name}] not found.");
  8982. }
  8983. protected function getPossibleViewFiles($name)
  8984. {
  8985. return array_map(function ($extension) use($name) {
  8986. return str_replace('.', '/', $name) . '.' . $extension;
  8987. }, $this->extensions);
  8988. }
  8989. public function addLocation($location)
  8990. {
  8991. $this->paths[] = $location;
  8992. }
  8993. public function addNamespace($namespace, $hints)
  8994. {
  8995. $hints = (array) $hints;
  8996. if (isset($this->hints[$namespace])) {
  8997. $hints = array_merge($this->hints[$namespace], $hints);
  8998. }
  8999. $this->hints[$namespace] = $hints;
  9000. }
  9001. public function prependNamespace($namespace, $hints)
  9002. {
  9003. $hints = (array) $hints;
  9004. if (isset($this->hints[$namespace])) {
  9005. $hints = array_merge($hints, $this->hints[$namespace]);
  9006. }
  9007. $this->hints[$namespace] = $hints;
  9008. }
  9009. public function addExtension($extension)
  9010. {
  9011. if (($index = array_search($extension, $this->extensions)) !== false) {
  9012. unset($this->extensions[$index]);
  9013. }
  9014. array_unshift($this->extensions, $extension);
  9015. }
  9016. public function hasHintInformation($name)
  9017. {
  9018. return strpos($name, static::HINT_PATH_DELIMITER) > 0;
  9019. }
  9020. public function getFilesystem()
  9021. {
  9022. return $this->files;
  9023. }
  9024. public function getPaths()
  9025. {
  9026. return $this->paths;
  9027. }
  9028. public function getHints()
  9029. {
  9030. return $this->hints;
  9031. }
  9032. public function getExtensions()
  9033. {
  9034. return $this->extensions;
  9035. }
  9036. }
  9037. namespace Illuminate\Support\Contracts;
  9038. interface MessageProviderInterface
  9039. {
  9040. public function getMessageBag();
  9041. }
  9042. namespace Illuminate\Support;
  9043. use Countable;
  9044. use JsonSerializable;
  9045. use Illuminate\Support\Contracts\JsonableInterface;
  9046. use Illuminate\Support\Contracts\ArrayableInterface;
  9047. use Illuminate\Support\Contracts\MessageProviderInterface;
  9048. class MessageBag implements ArrayableInterface, Countable, JsonableInterface, MessageProviderInterface, JsonSerializable
  9049. {
  9050. protected $messages = array();
  9051. protected $format = ':message';
  9052. public function __construct(array $messages = array())
  9053. {
  9054. foreach ($messages as $key => $value) {
  9055. $this->messages[$key] = (array) $value;
  9056. }
  9057. }
  9058. public function add($key, $message)
  9059. {
  9060. if ($this->isUnique($key, $message)) {
  9061. $this->messages[$key][] = $message;
  9062. }
  9063. return $this;
  9064. }
  9065. public function merge($messages)
  9066. {
  9067. if ($messages instanceof MessageProviderInterface) {
  9068. $messages = $messages->getMessageBag()->getMessages();
  9069. }
  9070. $this->messages = array_merge_recursive($this->messages, $messages);
  9071. return $this;
  9072. }
  9073. protected function isUnique($key, $message)
  9074. {
  9075. $messages = (array) $this->messages;
  9076. return !isset($messages[$key]) || !in_array($message, $messages[$key]);
  9077. }
  9078. public function has($key = null)
  9079. {
  9080. return $this->first($key) !== '';
  9081. }
  9082. public function first($key = null, $format = null)
  9083. {
  9084. $messages = is_null($key) ? $this->all($format) : $this->get($key, $format);
  9085. return count($messages) > 0 ? $messages[0] : '';
  9086. }
  9087. public function get($key, $format = null)
  9088. {
  9089. $format = $this->checkFormat($format);
  9090. if (array_key_exists($key, $this->messages)) {
  9091. return $this->transform($this->messages[$key], $format, $key);
  9092. }
  9093. return array();
  9094. }
  9095. public function all($format = null)
  9096. {
  9097. $format = $this->checkFormat($format);
  9098. $all = array();
  9099. foreach ($this->messages as $key => $messages) {
  9100. $all = array_merge($all, $this->transform($messages, $format, $key));
  9101. }
  9102. return $all;
  9103. }
  9104. protected function transform($messages, $format, $messageKey)
  9105. {
  9106. $messages = (array) $messages;
  9107. foreach ($messages as $key => &$message) {
  9108. $replace = array(':message', ':key');
  9109. $message = str_replace($replace, array($message, $messageKey), $format);
  9110. }
  9111. return $messages;
  9112. }
  9113. protected function checkFormat($format)
  9114. {
  9115. return $format === null ? $this->format : $format;
  9116. }
  9117. public function getMessages()
  9118. {
  9119. return $this->messages;
  9120. }
  9121. public function getMessageBag()
  9122. {
  9123. return $this;
  9124. }
  9125. public function getFormat()
  9126. {
  9127. return $this->format;
  9128. }
  9129. public function setFormat($format = ':message')
  9130. {
  9131. $this->format = $format;
  9132. return $this;
  9133. }
  9134. public function isEmpty()
  9135. {
  9136. return !$this->any();
  9137. }
  9138. public function any()
  9139. {
  9140. return $this->count() > 0;
  9141. }
  9142. public function count()
  9143. {
  9144. return count($this->messages, COUNT_RECURSIVE) - count($this->messages);
  9145. }
  9146. public function toArray()
  9147. {
  9148. return $this->getMessages();
  9149. }
  9150. public function jsonSerialize()
  9151. {
  9152. return $this->toArray();
  9153. }
  9154. public function toJson($options = 0)
  9155. {
  9156. return json_encode($this->toArray(), $options);
  9157. }
  9158. public function __toString()
  9159. {
  9160. return $this->toJson();
  9161. }
  9162. }
  9163. namespace Illuminate\Support\Facades;
  9164. class View extends Facade
  9165. {
  9166. protected static function getFacadeAccessor()
  9167. {
  9168. return 'view';
  9169. }
  9170. }
  9171. namespace Illuminate\Support\Contracts;
  9172. interface RenderableInterface
  9173. {
  9174. public function render();
  9175. }
  9176. namespace Illuminate\View;
  9177. use ArrayAccess;
  9178. use Closure;
  9179. use Illuminate\Support\MessageBag;
  9180. use Illuminate\View\Engines\EngineInterface;
  9181. use Illuminate\Support\Contracts\MessageProviderInterface;
  9182. use Illuminate\Support\Contracts\ArrayableInterface as Arrayable;
  9183. use Illuminate\Support\Contracts\RenderableInterface as Renderable;
  9184. class View implements ArrayAccess, Renderable
  9185. {
  9186. protected $factory;
  9187. protected $engine;
  9188. protected $view;
  9189. protected $data;
  9190. protected $path;
  9191. public function __construct(Factory $factory, EngineInterface $engine, $view, $path, $data = array())
  9192. {
  9193. $this->view = $view;
  9194. $this->path = $path;
  9195. $this->engine = $engine;
  9196. $this->factory = $factory;
  9197. $this->data = $data instanceof Arrayable ? $data->toArray() : (array) $data;
  9198. }
  9199. public function render(Closure $callback = null)
  9200. {
  9201. $contents = $this->renderContents();
  9202. $response = isset($callback) ? $callback($this, $contents) : null;
  9203. $this->factory->flushSectionsIfDoneRendering();
  9204. return $response ?: $contents;
  9205. }
  9206. protected function renderContents()
  9207. {
  9208. $this->factory->incrementRender();
  9209. $this->factory->callComposer($this);
  9210. $contents = $this->getContents();
  9211. $this->factory->decrementRender();
  9212. return $contents;
  9213. }
  9214. public function renderSections()
  9215. {
  9216. $env = $this->factory;
  9217. return $this->render(function ($view) use($env) {
  9218. return $env->getSections();
  9219. });
  9220. }
  9221. protected function getContents()
  9222. {
  9223. return $this->engine->get($this->path, $this->gatherData());
  9224. }
  9225. protected function gatherData()
  9226. {
  9227. $data = array_merge($this->factory->getShared(), $this->data);
  9228. foreach ($data as $key => $value) {
  9229. if ($value instanceof Renderable) {
  9230. $data[$key] = $value->render();
  9231. }
  9232. }
  9233. return $data;
  9234. }
  9235. public function with($key, $value = null)
  9236. {
  9237. if (is_array($key)) {
  9238. $this->data = array_merge($this->data, $key);
  9239. } else {
  9240. $this->data[$key] = $value;
  9241. }
  9242. return $this;
  9243. }
  9244. public function nest($key, $view, array $data = array())
  9245. {
  9246. return $this->with($key, $this->factory->make($view, $data));
  9247. }
  9248. public function withErrors($provider)
  9249. {
  9250. if ($provider instanceof MessageProviderInterface) {
  9251. $this->with('errors', $provider->getMessageBag());
  9252. } else {
  9253. $this->with('errors', new MessageBag((array) $provider));
  9254. }
  9255. return $this;
  9256. }
  9257. public function getFactory()
  9258. {
  9259. return $this->factory;
  9260. }
  9261. public function getEngine()
  9262. {
  9263. return $this->engine;
  9264. }
  9265. public function getName()
  9266. {
  9267. return $this->view;
  9268. }
  9269. public function getData()
  9270. {
  9271. return $this->data;
  9272. }
  9273. public function getPath()
  9274. {
  9275. return $this->path;
  9276. }
  9277. public function setPath($path)
  9278. {
  9279. $this->path = $path;
  9280. }
  9281. public function offsetExists($key)
  9282. {
  9283. return array_key_exists($key, $this->data);
  9284. }
  9285. public function offsetGet($key)
  9286. {
  9287. return $this->data[$key];
  9288. }
  9289. public function offsetSet($key, $value)
  9290. {
  9291. $this->with($key, $value);
  9292. }
  9293. public function offsetUnset($key)
  9294. {
  9295. unset($this->data[$key]);
  9296. }
  9297. public function &__get($key)
  9298. {
  9299. return $this->data[$key];
  9300. }
  9301. public function __set($key, $value)
  9302. {
  9303. $this->with($key, $value);
  9304. }
  9305. public function __isset($key)
  9306. {
  9307. return isset($this->data[$key]);
  9308. }
  9309. public function __unset($key)
  9310. {
  9311. unset($this->data[$key]);
  9312. }
  9313. public function __call($method, $parameters)
  9314. {
  9315. if (starts_with($method, 'with')) {
  9316. return $this->with(snake_case(substr($method, 4)), $parameters[0]);
  9317. }
  9318. throw new \BadMethodCallException("Method [{$method}] does not exist on view.");
  9319. }
  9320. public function __toString()
  9321. {
  9322. return $this->render();
  9323. }
  9324. }
  9325. namespace Illuminate\View\Engines;
  9326. interface EngineInterface
  9327. {
  9328. public function get($path, array $data = array());
  9329. }
  9330. namespace Illuminate\View\Engines;
  9331. use Illuminate\View\Exception;
  9332. class PhpEngine implements EngineInterface
  9333. {
  9334. public function get($path, array $data = array())
  9335. {
  9336. return $this->evaluatePath($path, $data);
  9337. }
  9338. protected function evaluatePath($__path, $__data)
  9339. {
  9340. ob_start();
  9341. extract($__data);
  9342. try {
  9343. include $__path;
  9344. } catch (\Exception $e) {
  9345. $this->handleViewException($e);
  9346. }
  9347. return ltrim(ob_get_clean());
  9348. }
  9349. protected function handleViewException($e)
  9350. {
  9351. ob_get_clean();
  9352. throw $e;
  9353. }
  9354. }
  9355. namespace Symfony\Component\HttpFoundation;
  9356. class Response
  9357. {
  9358. const HTTP_CONTINUE = 100;
  9359. const HTTP_SWITCHING_PROTOCOLS = 101;
  9360. const HTTP_PROCESSING = 102;
  9361. const HTTP_OK = 200;
  9362. const HTTP_CREATED = 201;
  9363. const HTTP_ACCEPTED = 202;
  9364. const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
  9365. const HTTP_NO_CONTENT = 204;
  9366. const HTTP_RESET_CONTENT = 205;
  9367. const HTTP_PARTIAL_CONTENT = 206;
  9368. const HTTP_MULTI_STATUS = 207;
  9369. const HTTP_ALREADY_REPORTED = 208;
  9370. const HTTP_IM_USED = 226;
  9371. const HTTP_MULTIPLE_CHOICES = 300;
  9372. const HTTP_MOVED_PERMANENTLY = 301;
  9373. const HTTP_FOUND = 302;
  9374. const HTTP_SEE_OTHER = 303;
  9375. const HTTP_NOT_MODIFIED = 304;
  9376. const HTTP_USE_PROXY = 305;
  9377. const HTTP_RESERVED = 306;
  9378. const HTTP_TEMPORARY_REDIRECT = 307;
  9379. const HTTP_PERMANENTLY_REDIRECT = 308;
  9380. const HTTP_BAD_REQUEST = 400;
  9381. const HTTP_UNAUTHORIZED = 401;
  9382. const HTTP_PAYMENT_REQUIRED = 402;
  9383. const HTTP_FORBIDDEN = 403;
  9384. const HTTP_NOT_FOUND = 404;
  9385. const HTTP_METHOD_NOT_ALLOWED = 405;
  9386. const HTTP_NOT_ACCEPTABLE = 406;
  9387. const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
  9388. const HTTP_REQUEST_TIMEOUT = 408;
  9389. const HTTP_CONFLICT = 409;
  9390. const HTTP_GONE = 410;
  9391. const HTTP_LENGTH_REQUIRED = 411;
  9392. const HTTP_PRECONDITION_FAILED = 412;
  9393. const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
  9394. const HTTP_REQUEST_URI_TOO_LONG = 414;
  9395. const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
  9396. const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
  9397. const HTTP_EXPECTATION_FAILED = 417;
  9398. const HTTP_I_AM_A_TEAPOT = 418;
  9399. const HTTP_UNPROCESSABLE_ENTITY = 422;
  9400. const HTTP_LOCKED = 423;
  9401. const HTTP_FAILED_DEPENDENCY = 424;
  9402. const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;
  9403. const HTTP_UPGRADE_REQUIRED = 426;
  9404. const HTTP_PRECONDITION_REQUIRED = 428;
  9405. const HTTP_TOO_MANY_REQUESTS = 429;
  9406. const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
  9407. const HTTP_INTERNAL_SERVER_ERROR = 500;
  9408. const HTTP_NOT_IMPLEMENTED = 501;
  9409. const HTTP_BAD_GATEWAY = 502;
  9410. const HTTP_SERVICE_UNAVAILABLE = 503;
  9411. const HTTP_GATEWAY_TIMEOUT = 504;
  9412. const HTTP_VERSION_NOT_SUPPORTED = 505;
  9413. const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;
  9414. const HTTP_INSUFFICIENT_STORAGE = 507;
  9415. const HTTP_LOOP_DETECTED = 508;
  9416. const HTTP_NOT_EXTENDED = 510;
  9417. const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
  9418. public $headers;
  9419. protected $content;
  9420. protected $version;
  9421. protected $statusCode;
  9422. protected $statusText;
  9423. protected $charset;
  9424. public static $statusTexts = array(100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Reserved', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Requested Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Reserved for WebDAV advanced collections expired proposal', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates (Experimental)', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required');
  9425. public function __construct($content = '', $status = 200, $headers = array())
  9426. {
  9427. $this->headers = new ResponseHeaderBag($headers);
  9428. $this->setContent($content);
  9429. $this->setStatusCode($status);
  9430. $this->setProtocolVersion('1.0');
  9431. if (!$this->headers->has('Date')) {
  9432. $this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
  9433. }
  9434. }
  9435. public static function create($content = '', $status = 200, $headers = array())
  9436. {
  9437. return new static($content, $status, $headers);
  9438. }
  9439. public function __toString()
  9440. {
  9441. return sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText) . '
  9442. ' . $this->headers . '
  9443. ' . $this->getContent();
  9444. }
  9445. public function __clone()
  9446. {
  9447. $this->headers = clone $this->headers;
  9448. }
  9449. public function prepare(Request $request)
  9450. {
  9451. $headers = $this->headers;
  9452. if ($this->isInformational() || in_array($this->statusCode, array(204, 304))) {
  9453. $this->setContent(null);
  9454. }
  9455. if (!$headers->has('Content-Type')) {
  9456. $format = $request->getRequestFormat();
  9457. if (null !== $format && ($mimeType = $request->getMimeType($format))) {
  9458. $headers->set('Content-Type', $mimeType);
  9459. }
  9460. }
  9461. $charset = $this->charset ?: 'UTF-8';
  9462. if (!$headers->has('Content-Type')) {
  9463. $headers->set('Content-Type', 'text/html; charset=' . $charset);
  9464. } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
  9465. $headers->set('Content-Type', $headers->get('Content-Type') . '; charset=' . $charset);
  9466. }
  9467. if ($headers->has('Transfer-Encoding')) {
  9468. $headers->remove('Content-Length');
  9469. }
  9470. if ($request->isMethod('HEAD')) {
  9471. $length = $headers->get('Content-Length');
  9472. $this->setContent(null);
  9473. if ($length) {
  9474. $headers->set('Content-Length', $length);
  9475. }
  9476. }
  9477. if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) {
  9478. $this->setProtocolVersion('1.1');
  9479. }
  9480. if ('1.0' == $this->getProtocolVersion() && 'no-cache' == $this->headers->get('Cache-Control')) {
  9481. $this->headers->set('pragma', 'no-cache');
  9482. $this->headers->set('expires', -1);
  9483. }
  9484. $this->ensureIEOverSSLCompatibility($request);
  9485. return $this;
  9486. }
  9487. public function sendHeaders()
  9488. {
  9489. if (headers_sent()) {
  9490. return $this;
  9491. }
  9492. header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode);
  9493. foreach ($this->headers->allPreserveCase() as $name => $values) {
  9494. foreach ($values as $value) {
  9495. header($name . ': ' . $value, false, $this->statusCode);
  9496. }
  9497. }
  9498. foreach ($this->headers->getCookies() as $cookie) {
  9499. setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly());
  9500. }
  9501. return $this;
  9502. }
  9503. public function sendContent()
  9504. {
  9505. echo $this->content;
  9506. return $this;
  9507. }
  9508. public function send()
  9509. {
  9510. $this->sendHeaders();
  9511. $this->sendContent();
  9512. if (function_exists('fastcgi_finish_request')) {
  9513. fastcgi_finish_request();
  9514. } elseif ('cli' !== PHP_SAPI) {
  9515. static::closeOutputBuffers(0, true);
  9516. flush();
  9517. }
  9518. return $this;
  9519. }
  9520. public function setContent($content)
  9521. {
  9522. if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) {
  9523. throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content)));
  9524. }
  9525. $this->content = (string) $content;
  9526. return $this;
  9527. }
  9528. public function getContent()
  9529. {
  9530. return $this->content;
  9531. }
  9532. public function setProtocolVersion($version)
  9533. {
  9534. $this->version = $version;
  9535. return $this;
  9536. }
  9537. public function getProtocolVersion()
  9538. {
  9539. return $this->version;
  9540. }
  9541. public function setStatusCode($code, $text = null)
  9542. {
  9543. $this->statusCode = $code = (int) $code;
  9544. if ($this->isInvalid()) {
  9545. throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code));
  9546. }
  9547. if (null === $text) {
  9548. $this->statusText = isset(self::$statusTexts[$code]) ? self::$statusTexts[$code] : '';
  9549. return $this;
  9550. }
  9551. if (false === $text) {
  9552. $this->statusText = '';
  9553. return $this;
  9554. }
  9555. $this->statusText = $text;
  9556. return $this;
  9557. }
  9558. public function getStatusCode()
  9559. {
  9560. return $this->statusCode;
  9561. }
  9562. public function setCharset($charset)
  9563. {
  9564. $this->charset = $charset;
  9565. return $this;
  9566. }
  9567. public function getCharset()
  9568. {
  9569. return $this->charset;
  9570. }
  9571. public function isCacheable()
  9572. {
  9573. if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) {
  9574. return false;
  9575. }
  9576. if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) {
  9577. return false;
  9578. }
  9579. return $this->isValidateable() || $this->isFresh();
  9580. }
  9581. public function isFresh()
  9582. {
  9583. return $this->getTtl() > 0;
  9584. }
  9585. public function isValidateable()
  9586. {
  9587. return $this->headers->has('Last-Modified') || $this->headers->has('ETag');
  9588. }
  9589. public function setPrivate()
  9590. {
  9591. $this->headers->removeCacheControlDirective('public');
  9592. $this->headers->addCacheControlDirective('private');
  9593. return $this;
  9594. }
  9595. public function setPublic()
  9596. {
  9597. $this->headers->addCacheControlDirective('public');
  9598. $this->headers->removeCacheControlDirective('private');
  9599. return $this;
  9600. }
  9601. public function mustRevalidate()
  9602. {
  9603. return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->has('proxy-revalidate');
  9604. }
  9605. public function getDate()
  9606. {
  9607. return $this->headers->getDate('Date', new \DateTime());
  9608. }
  9609. public function setDate(\DateTime $date)
  9610. {
  9611. $date->setTimezone(new \DateTimeZone('UTC'));
  9612. $this->headers->set('Date', $date->format('D, d M Y H:i:s') . ' GMT');
  9613. return $this;
  9614. }
  9615. public function getAge()
  9616. {
  9617. if (null !== ($age = $this->headers->get('Age'))) {
  9618. return (int) $age;
  9619. }
  9620. return max(time() - $this->getDate()->format('U'), 0);
  9621. }
  9622. public function expire()
  9623. {
  9624. if ($this->isFresh()) {
  9625. $this->headers->set('Age', $this->getMaxAge());
  9626. }
  9627. return $this;
  9628. }
  9629. public function getExpires()
  9630. {
  9631. try {
  9632. return $this->headers->getDate('Expires');
  9633. } catch (\RuntimeException $e) {
  9634. return \DateTime::createFromFormat(DATE_RFC2822, 'Sat, 01 Jan 00 00:00:00 +0000');
  9635. }
  9636. }
  9637. public function setExpires(\DateTime $date = null)
  9638. {
  9639. if (null === $date) {
  9640. $this->headers->remove('Expires');
  9641. } else {
  9642. $date = clone $date;
  9643. $date->setTimezone(new \DateTimeZone('UTC'));
  9644. $this->headers->set('Expires', $date->format('D, d M Y H:i:s') . ' GMT');
  9645. }
  9646. return $this;
  9647. }
  9648. public function getMaxAge()
  9649. {
  9650. if ($this->headers->hasCacheControlDirective('s-maxage')) {
  9651. return (int) $this->headers->getCacheControlDirective('s-maxage');
  9652. }
  9653. if ($this->headers->hasCacheControlDirective('max-age')) {
  9654. return (int) $this->headers->getCacheControlDirective('max-age');
  9655. }
  9656. if (null !== $this->getExpires()) {
  9657. return $this->getExpires()->format('U') - $this->getDate()->format('U');
  9658. }
  9659. }
  9660. public function setMaxAge($value)
  9661. {
  9662. $this->headers->addCacheControlDirective('max-age', $value);
  9663. return $this;
  9664. }
  9665. public function setSharedMaxAge($value)
  9666. {
  9667. $this->setPublic();
  9668. $this->headers->addCacheControlDirective('s-maxage', $value);
  9669. return $this;
  9670. }
  9671. public function getTtl()
  9672. {
  9673. if (null !== ($maxAge = $this->getMaxAge())) {
  9674. return $maxAge - $this->getAge();
  9675. }
  9676. }
  9677. public function setTtl($seconds)
  9678. {
  9679. $this->setSharedMaxAge($this->getAge() + $seconds);
  9680. return $this;
  9681. }
  9682. public function setClientTtl($seconds)
  9683. {
  9684. $this->setMaxAge($this->getAge() + $seconds);
  9685. return $this;
  9686. }
  9687. public function getLastModified()
  9688. {
  9689. return $this->headers->getDate('Last-Modified');
  9690. }
  9691. public function setLastModified(\DateTime $date = null)
  9692. {
  9693. if (null === $date) {
  9694. $this->headers->remove('Last-Modified');
  9695. } else {
  9696. $date = clone $date;
  9697. $date->setTimezone(new \DateTimeZone('UTC'));
  9698. $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s') . ' GMT');
  9699. }
  9700. return $this;
  9701. }
  9702. public function getEtag()
  9703. {
  9704. return $this->headers->get('ETag');
  9705. }
  9706. public function setEtag($etag = null, $weak = false)
  9707. {
  9708. if (null === $etag) {
  9709. $this->headers->remove('Etag');
  9710. } else {
  9711. if (0 !== strpos($etag, '"')) {
  9712. $etag = '"' . $etag . '"';
  9713. }
  9714. $this->headers->set('ETag', (true === $weak ? 'W/' : '') . $etag);
  9715. }
  9716. return $this;
  9717. }
  9718. public function setCache(array $options)
  9719. {
  9720. if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) {
  9721. throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff))));
  9722. }
  9723. if (isset($options['etag'])) {
  9724. $this->setEtag($options['etag']);
  9725. }
  9726. if (isset($options['last_modified'])) {
  9727. $this->setLastModified($options['last_modified']);
  9728. }
  9729. if (isset($options['max_age'])) {
  9730. $this->setMaxAge($options['max_age']);
  9731. }
  9732. if (isset($options['s_maxage'])) {
  9733. $this->setSharedMaxAge($options['s_maxage']);
  9734. }
  9735. if (isset($options['public'])) {
  9736. if ($options['public']) {
  9737. $this->setPublic();
  9738. } else {
  9739. $this->setPrivate();
  9740. }
  9741. }
  9742. if (isset($options['private'])) {
  9743. if ($options['private']) {
  9744. $this->setPrivate();
  9745. } else {
  9746. $this->setPublic();
  9747. }
  9748. }
  9749. return $this;
  9750. }
  9751. public function setNotModified()
  9752. {
  9753. $this->setStatusCode(304);
  9754. $this->setContent(null);
  9755. foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) {
  9756. $this->headers->remove($header);
  9757. }
  9758. return $this;
  9759. }
  9760. public function hasVary()
  9761. {
  9762. return null !== $this->headers->get('Vary');
  9763. }
  9764. public function getVary()
  9765. {
  9766. if (!($vary = $this->headers->get('Vary', null, false))) {
  9767. return array();
  9768. }
  9769. $ret = array();
  9770. foreach ($vary as $item) {
  9771. $ret = array_merge($ret, preg_split('/[\\s,]+/', $item));
  9772. }
  9773. return $ret;
  9774. }
  9775. public function setVary($headers, $replace = true)
  9776. {
  9777. $this->headers->set('Vary', $headers, $replace);
  9778. return $this;
  9779. }
  9780. public function isNotModified(Request $request)
  9781. {
  9782. if (!$request->isMethodSafe()) {
  9783. return false;
  9784. }
  9785. $lastModified = $request->headers->get('If-Modified-Since');
  9786. $notModified = false;
  9787. if ($etags = $request->getEtags()) {
  9788. $notModified = (in_array($this->getEtag(), $etags) || in_array('*', $etags)) && (!$lastModified || $this->headers->get('Last-Modified') == $lastModified);
  9789. } elseif ($lastModified) {
  9790. $notModified = $lastModified == $this->headers->get('Last-Modified');
  9791. }
  9792. if ($notModified) {
  9793. $this->setNotModified();
  9794. }
  9795. return $notModified;
  9796. }
  9797. public function isInvalid()
  9798. {
  9799. return $this->statusCode < 100 || $this->statusCode >= 600;
  9800. }
  9801. public function isInformational()
  9802. {
  9803. return $this->statusCode >= 100 && $this->statusCode < 200;
  9804. }
  9805. public function isSuccessful()
  9806. {
  9807. return $this->statusCode >= 200 && $this->statusCode < 300;
  9808. }
  9809. public function isRedirection()
  9810. {
  9811. return $this->statusCode >= 300 && $this->statusCode < 400;
  9812. }
  9813. public function isClientError()
  9814. {
  9815. return $this->statusCode >= 400 && $this->statusCode < 500;
  9816. }
  9817. public function isServerError()
  9818. {
  9819. return $this->statusCode >= 500 && $this->statusCode < 600;
  9820. }
  9821. public function isOk()
  9822. {
  9823. return 200 === $this->statusCode;
  9824. }
  9825. public function isForbidden()
  9826. {
  9827. return 403 === $this->statusCode;
  9828. }
  9829. public function isNotFound()
  9830. {
  9831. return 404 === $this->statusCode;
  9832. }
  9833. public function isRedirect($location = null)
  9834. {
  9835. return in_array($this->statusCode, array(201, 301, 302, 303, 307, 308)) && (null === $location ?: $location == $this->headers->get('Location'));
  9836. }
  9837. public function isEmpty()
  9838. {
  9839. return in_array($this->statusCode, array(204, 304));
  9840. }
  9841. public static function closeOutputBuffers($targetLevel, $flush)
  9842. {
  9843. $status = ob_get_status(true);
  9844. $level = count($status);
  9845. while ($level-- > $targetLevel && (!empty($status[$level]['del']) || isset($status[$level]['flags']) && $status[$level]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE && $status[$level]['flags'] & ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE))) {
  9846. if ($flush) {
  9847. ob_end_flush();
  9848. } else {
  9849. ob_end_clean();
  9850. }
  9851. }
  9852. }
  9853. protected function ensureIEOverSSLCompatibility(Request $request)
  9854. {
  9855. if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) {
  9856. if (intval(preg_replace('/(MSIE )(.*?);/', '$2', $match[0])) < 9) {
  9857. $this->headers->remove('Cache-Control');
  9858. }
  9859. }
  9860. }
  9861. }
  9862. namespace Illuminate\Http;
  9863. use ArrayObject;
  9864. use Illuminate\Support\Contracts\JsonableInterface;
  9865. use Illuminate\Support\Contracts\RenderableInterface;
  9866. class Response extends \Symfony\Component\HttpFoundation\Response
  9867. {
  9868. use ResponseTrait;
  9869. public $original;
  9870. public function setContent($content)
  9871. {
  9872. $this->original = $content;
  9873. if ($this->shouldBeJson($content)) {
  9874. $this->headers->set('Content-Type', 'application/json');
  9875. $content = $this->morphToJson($content);
  9876. } elseif ($content instanceof RenderableInterface) {
  9877. $content = $content->render();
  9878. }
  9879. return parent::setContent($content);
  9880. }
  9881. protected function morphToJson($content)
  9882. {
  9883. if ($content instanceof JsonableInterface) {
  9884. return $content->toJson();
  9885. }
  9886. return json_encode($content);
  9887. }
  9888. protected function shouldBeJson($content)
  9889. {
  9890. return $content instanceof JsonableInterface || $content instanceof ArrayObject || is_array($content);
  9891. }
  9892. public function getOriginalContent()
  9893. {
  9894. return $this->original;
  9895. }
  9896. }
  9897. namespace Symfony\Component\HttpFoundation;
  9898. class ResponseHeaderBag extends HeaderBag
  9899. {
  9900. const COOKIES_FLAT = 'flat';
  9901. const COOKIES_ARRAY = 'array';
  9902. const DISPOSITION_ATTACHMENT = 'attachment';
  9903. const DISPOSITION_INLINE = 'inline';
  9904. protected $computedCacheControl = array();
  9905. protected $cookies = array();
  9906. protected $headerNames = array();
  9907. public function __construct(array $headers = array())
  9908. {
  9909. parent::__construct($headers);
  9910. if (!isset($this->headers['cache-control'])) {
  9911. $this->set('Cache-Control', '');
  9912. }
  9913. }
  9914. public function __toString()
  9915. {
  9916. $cookies = '';
  9917. foreach ($this->getCookies() as $cookie) {
  9918. $cookies .= 'Set-Cookie: ' . $cookie . '
  9919. ';
  9920. }
  9921. ksort($this->headerNames);
  9922. return parent::__toString() . $cookies;
  9923. }
  9924. public function allPreserveCase()
  9925. {
  9926. return array_combine($this->headerNames, $this->headers);
  9927. }
  9928. public function replace(array $headers = array())
  9929. {
  9930. $this->headerNames = array();
  9931. parent::replace($headers);
  9932. if (!isset($this->headers['cache-control'])) {
  9933. $this->set('Cache-Control', '');
  9934. }
  9935. }
  9936. public function set($key, $values, $replace = true)
  9937. {
  9938. parent::set($key, $values, $replace);
  9939. $uniqueKey = strtr(strtolower($key), '_', '-');
  9940. $this->headerNames[$uniqueKey] = $key;
  9941. if (in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'))) {
  9942. $computed = $this->computeCacheControlValue();
  9943. $this->headers['cache-control'] = array($computed);
  9944. $this->headerNames['cache-control'] = 'Cache-Control';
  9945. $this->computedCacheControl = $this->parseCacheControl($computed);
  9946. }
  9947. }
  9948. public function remove($key)
  9949. {
  9950. parent::remove($key);
  9951. $uniqueKey = strtr(strtolower($key), '_', '-');
  9952. unset($this->headerNames[$uniqueKey]);
  9953. if ('cache-control' === $uniqueKey) {
  9954. $this->computedCacheControl = array();
  9955. }
  9956. }
  9957. public function hasCacheControlDirective($key)
  9958. {
  9959. return array_key_exists($key, $this->computedCacheControl);
  9960. }
  9961. public function getCacheControlDirective($key)
  9962. {
  9963. return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null;
  9964. }
  9965. public function setCookie(Cookie $cookie)
  9966. {
  9967. $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
  9968. }
  9969. public function removeCookie($name, $path = '/', $domain = null)
  9970. {
  9971. if (null === $path) {
  9972. $path = '/';
  9973. }
  9974. unset($this->cookies[$domain][$path][$name]);
  9975. if (empty($this->cookies[$domain][$path])) {
  9976. unset($this->cookies[$domain][$path]);
  9977. if (empty($this->cookies[$domain])) {
  9978. unset($this->cookies[$domain]);
  9979. }
  9980. }
  9981. }
  9982. public function getCookies($format = self::COOKIES_FLAT)
  9983. {
  9984. if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) {
  9985. throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY))));
  9986. }
  9987. if (self::COOKIES_ARRAY === $format) {
  9988. return $this->cookies;
  9989. }
  9990. $flattenedCookies = array();
  9991. foreach ($this->cookies as $path) {
  9992. foreach ($path as $cookies) {
  9993. foreach ($cookies as $cookie) {
  9994. $flattenedCookies[] = $cookie;
  9995. }
  9996. }
  9997. }
  9998. return $flattenedCookies;
  9999. }
  10000. public function clearCookie($name, $path = '/', $domain = null)
  10001. {
  10002. $this->setCookie(new Cookie($name, null, 1, $path, $domain));
  10003. }
  10004. public function makeDisposition($disposition, $filename, $filenameFallback = '')
  10005. {
  10006. if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
  10007. throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
  10008. }
  10009. if ('' == $filenameFallback) {
  10010. $filenameFallback = $filename;
  10011. }
  10012. if (!preg_match('/^[\\x20-\\x7e]*$/', $filenameFallback)) {
  10013. throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
  10014. }
  10015. if (false !== strpos($filenameFallback, '%')) {
  10016. throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
  10017. }
  10018. if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
  10019. throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
  10020. }
  10021. $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback));
  10022. if ($filename !== $filenameFallback) {
  10023. $output .= sprintf('; filename*=utf-8\'\'%s', rawurlencode($filename));
  10024. }
  10025. return $output;
  10026. }
  10027. protected function computeCacheControlValue()
  10028. {
  10029. if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) {
  10030. return 'no-cache';
  10031. }
  10032. if (!$this->cacheControl) {
  10033. return 'private, must-revalidate';
  10034. }
  10035. $header = $this->getCacheControlHeader();
  10036. if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
  10037. return $header;
  10038. }
  10039. if (!isset($this->cacheControl['s-maxage'])) {
  10040. return $header . ', private';
  10041. }
  10042. return $header;
  10043. }
  10044. }
  10045. namespace Symfony\Component\HttpFoundation;
  10046. class Cookie
  10047. {
  10048. protected $name;
  10049. protected $value;
  10050. protected $domain;
  10051. protected $expire;
  10052. protected $path;
  10053. protected $secure;
  10054. protected $httpOnly;
  10055. public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true)
  10056. {
  10057. if (preg_match('/[=,;
  10058. ]/', $name)) {
  10059. throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name));
  10060. }
  10061. if (empty($name)) {
  10062. throw new \InvalidArgumentException('The cookie name cannot be empty.');
  10063. }
  10064. if ($expire instanceof \DateTime) {
  10065. $expire = $expire->format('U');
  10066. } elseif (!is_numeric($expire)) {
  10067. $expire = strtotime($expire);
  10068. if (false === $expire || -1 === $expire) {
  10069. throw new \InvalidArgumentException('The cookie expiration time is not valid.');
  10070. }
  10071. }
  10072. $this->name = $name;
  10073. $this->value = $value;
  10074. $this->domain = $domain;
  10075. $this->expire = $expire;
  10076. $this->path = empty($path) ? '/' : $path;
  10077. $this->secure = (bool) $secure;
  10078. $this->httpOnly = (bool) $httpOnly;
  10079. }
  10080. public function __toString()
  10081. {
  10082. $str = urlencode($this->getName()) . '=';
  10083. if ('' === (string) $this->getValue()) {
  10084. $str .= 'deleted; expires=' . gmdate('D, d-M-Y H:i:s T', time() - 31536001);
  10085. } else {
  10086. $str .= urlencode($this->getValue());
  10087. if ($this->getExpiresTime() !== 0) {
  10088. $str .= '; expires=' . gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime());
  10089. }
  10090. }
  10091. if ($this->path) {
  10092. $str .= '; path=' . $this->path;
  10093. }
  10094. if ($this->getDomain()) {
  10095. $str .= '; domain=' . $this->getDomain();
  10096. }
  10097. if (true === $this->isSecure()) {
  10098. $str .= '; secure';
  10099. }
  10100. if (true === $this->isHttpOnly()) {
  10101. $str .= '; httponly';
  10102. }
  10103. return $str;
  10104. }
  10105. public function getName()
  10106. {
  10107. return $this->name;
  10108. }
  10109. public function getValue()
  10110. {
  10111. return $this->value;
  10112. }
  10113. public function getDomain()
  10114. {
  10115. return $this->domain;
  10116. }
  10117. public function getExpiresTime()
  10118. {
  10119. return $this->expire;
  10120. }
  10121. public function getPath()
  10122. {
  10123. return $this->path;
  10124. }
  10125. public function isSecure()
  10126. {
  10127. return $this->secure;
  10128. }
  10129. public function isHttpOnly()
  10130. {
  10131. return $this->httpOnly;
  10132. }
  10133. public function isCleared()
  10134. {
  10135. return $this->expire < time();
  10136. }
  10137. }
  10138. namespace Whoops;
  10139. use Whoops\Handler\HandlerInterface;
  10140. use Whoops\Handler\Handler;
  10141. use Whoops\Handler\CallbackHandler;
  10142. use Whoops\Exception\Inspector;
  10143. use Whoops\Exception\ErrorException;
  10144. use InvalidArgumentException;
  10145. use Exception;
  10146. class Run
  10147. {
  10148. const EXCEPTION_HANDLER = 'handleException';
  10149. const ERROR_HANDLER = 'handleError';
  10150. const SHUTDOWN_HANDLER = 'handleShutdown';
  10151. protected $isRegistered;
  10152. protected $allowQuit = true;
  10153. protected $sendOutput = true;
  10154. protected $sendHttpCode = 500;
  10155. protected $handlerStack = array();
  10156. protected $silencedPatterns = array();
  10157. public function pushHandler($handler)
  10158. {
  10159. if (is_callable($handler)) {
  10160. $handler = new CallbackHandler($handler);
  10161. }
  10162. if (!$handler instanceof HandlerInterface) {
  10163. throw new InvalidArgumentException('Argument to ' . __METHOD__ . ' must be a callable, or instance of' . 'Whoops\\Handler\\HandlerInterface');
  10164. }
  10165. $this->handlerStack[] = $handler;
  10166. return $this;
  10167. }
  10168. public function popHandler()
  10169. {
  10170. return array_pop($this->handlerStack);
  10171. }
  10172. public function getHandlers()
  10173. {
  10174. return $this->handlerStack;
  10175. }
  10176. public function clearHandlers()
  10177. {
  10178. $this->handlerStack = array();
  10179. return $this;
  10180. }
  10181. protected function getInspector(Exception $exception)
  10182. {
  10183. return new Inspector($exception);
  10184. }
  10185. public function register()
  10186. {
  10187. if (!$this->isRegistered) {
  10188. class_exists('\\Whoops\\Exception\\ErrorException');
  10189. class_exists('\\Whoops\\Exception\\FrameCollection');
  10190. class_exists('\\Whoops\\Exception\\Frame');
  10191. class_exists('\\Whoops\\Exception\\Inspector');
  10192. set_error_handler(array($this, self::ERROR_HANDLER));
  10193. set_exception_handler(array($this, self::EXCEPTION_HANDLER));
  10194. register_shutdown_function(array($this, self::SHUTDOWN_HANDLER));
  10195. $this->isRegistered = true;
  10196. }
  10197. return $this;
  10198. }
  10199. public function unregister()
  10200. {
  10201. if ($this->isRegistered) {
  10202. restore_exception_handler();
  10203. restore_error_handler();
  10204. $this->isRegistered = false;
  10205. }
  10206. return $this;
  10207. }
  10208. public function allowQuit($exit = null)
  10209. {
  10210. if (func_num_args() == 0) {
  10211. return $this->allowQuit;
  10212. }
  10213. return $this->allowQuit = (bool) $exit;
  10214. }
  10215. public function silenceErrorsInPaths($patterns, $levels = 10240)
  10216. {
  10217. $this->silencedPatterns = array_merge($this->silencedPatterns, array_map(function ($pattern) use($levels) {
  10218. return array('pattern' => $pattern, 'levels' => $levels);
  10219. }, (array) $patterns));
  10220. return $this;
  10221. }
  10222. public function sendHttpCode($code = null)
  10223. {
  10224. if (func_num_args() == 0) {
  10225. return $this->sendHttpCode;
  10226. }
  10227. if (!$code) {
  10228. return $this->sendHttpCode = false;
  10229. }
  10230. if ($code === true) {
  10231. $code = 500;
  10232. }
  10233. if ($code < 400 || 600 <= $code) {
  10234. throw new InvalidArgumentException("Invalid status code '{$code}', must be 4xx or 5xx");
  10235. }
  10236. return $this->sendHttpCode = $code;
  10237. }
  10238. public function writeToOutput($send = null)
  10239. {
  10240. if (func_num_args() == 0) {
  10241. return $this->sendOutput;
  10242. }
  10243. return $this->sendOutput = (bool) $send;
  10244. }
  10245. public function handleException(Exception $exception)
  10246. {
  10247. $inspector = $this->getInspector($exception);
  10248. ob_start();
  10249. $handlerResponse = null;
  10250. foreach (array_reverse($this->handlerStack) as $handler) {
  10251. $handler->setRun($this);
  10252. $handler->setInspector($inspector);
  10253. $handler->setException($exception);
  10254. $handlerResponse = $handler->handle($exception);
  10255. if (in_array($handlerResponse, array(Handler::LAST_HANDLER, Handler::QUIT))) {
  10256. break;
  10257. }
  10258. }
  10259. $willQuit = $handlerResponse == Handler::QUIT && $this->allowQuit();
  10260. $output = ob_get_clean();
  10261. if ($this->writeToOutput()) {
  10262. if ($willQuit) {
  10263. while (ob_get_level() > 0) {
  10264. ob_end_clean();
  10265. }
  10266. }
  10267. $this->writeToOutputNow($output);
  10268. }
  10269. if ($willQuit) {
  10270. die(1);
  10271. }
  10272. return $output;
  10273. }
  10274. public function handleError($level, $message, $file = null, $line = null)
  10275. {
  10276. if ($level & error_reporting()) {
  10277. foreach ($this->silencedPatterns as $entry) {
  10278. $pathMatches = (bool) preg_match($entry['pattern'], $file);
  10279. $levelMatches = $level & $entry['levels'];
  10280. if ($pathMatches && $levelMatches) {
  10281. return true;
  10282. }
  10283. }
  10284. $exception = new ErrorException($message, $level, 0, $file, $line);
  10285. if ($this->canThrowExceptions) {
  10286. throw $exception;
  10287. } else {
  10288. $this->handleException($exception);
  10289. }
  10290. }
  10291. }
  10292. public function handleShutdown()
  10293. {
  10294. $this->canThrowExceptions = false;
  10295. $error = error_get_last();
  10296. if ($error && $this->isLevelFatal($error['type'])) {
  10297. $this->handleError($error['type'], $error['message'], $error['file'], $error['line']);
  10298. }
  10299. }
  10300. private $canThrowExceptions = true;
  10301. private function writeToOutputNow($output)
  10302. {
  10303. if ($this->sendHttpCode() && \Whoops\Util\Misc::canSendHeaders()) {
  10304. $httpCode = $this->sendHttpCode();
  10305. if (function_exists('http_response_code')) {
  10306. http_response_code($httpCode);
  10307. } else {
  10308. header('X-Ignore-This: 1', true, $httpCode);
  10309. }
  10310. }
  10311. echo $output;
  10312. return $this;
  10313. }
  10314. private static function isLevelFatal($level)
  10315. {
  10316. return in_array($level, array(E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING));
  10317. }
  10318. }
  10319. namespace Whoops\Handler;
  10320. use Whoops\Exception\Inspector;
  10321. use Whoops\Run;
  10322. use Exception;
  10323. interface HandlerInterface
  10324. {
  10325. public function handle();
  10326. public function setRun(Run $run);
  10327. public function setException(Exception $exception);
  10328. public function setInspector(Inspector $inspector);
  10329. }
  10330. namespace Whoops\Handler;
  10331. use Whoops\Handler\HandlerInterface;
  10332. use Whoops\Exception\Inspector;
  10333. use Whoops\Run;
  10334. use Exception;
  10335. abstract class Handler implements HandlerInterface
  10336. {
  10337. const DONE = 16;
  10338. const LAST_HANDLER = 32;
  10339. const QUIT = 48;
  10340. private $run;
  10341. private $inspector;
  10342. private $exception;
  10343. public function setRun(Run $run)
  10344. {
  10345. $this->run = $run;
  10346. }
  10347. protected function getRun()
  10348. {
  10349. return $this->run;
  10350. }
  10351. public function setInspector(Inspector $inspector)
  10352. {
  10353. $this->inspector = $inspector;
  10354. }
  10355. protected function getInspector()
  10356. {
  10357. return $this->inspector;
  10358. }
  10359. public function setException(Exception $exception)
  10360. {
  10361. $this->exception = $exception;
  10362. }
  10363. protected function getException()
  10364. {
  10365. return $this->exception;
  10366. }
  10367. }
  10368. namespace Whoops\Handler;
  10369. use Whoops\Handler\Handler;
  10370. use Whoops\Exception\Formatter;
  10371. class JsonResponseHandler extends Handler
  10372. {
  10373. private $returnFrames = false;
  10374. private $onlyForAjaxRequests = false;
  10375. public function addTraceToOutput($returnFrames = null)
  10376. {
  10377. if (func_num_args() == 0) {
  10378. return $this->returnFrames;
  10379. }
  10380. $this->returnFrames = (bool) $returnFrames;
  10381. return $this;
  10382. }
  10383. public function onlyForAjaxRequests($onlyForAjaxRequests = null)
  10384. {
  10385. if (func_num_args() == 0) {
  10386. return $this->onlyForAjaxRequests;
  10387. }
  10388. $this->onlyForAjaxRequests = (bool) $onlyForAjaxRequests;
  10389. }
  10390. private function isAjaxRequest()
  10391. {
  10392. return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
  10393. }
  10394. public function handle()
  10395. {
  10396. if ($this->onlyForAjaxRequests() && !$this->isAjaxRequest()) {
  10397. return Handler::DONE;
  10398. }
  10399. $response = array('error' => Formatter::formatExceptionAsDataArray($this->getInspector(), $this->addTraceToOutput()));
  10400. if (\Whoops\Util\Misc::canSendHeaders()) {
  10401. header('Content-Type: application/json');
  10402. }
  10403. echo json_encode($response);
  10404. return Handler::QUIT;
  10405. }
  10406. }
  10407. namespace Stack;
  10408. use Symfony\Component\HttpKernel\HttpKernelInterface;
  10409. class Builder
  10410. {
  10411. private $specs;
  10412. public function __construct()
  10413. {
  10414. $this->specs = new \SplStack();
  10415. }
  10416. public function unshift()
  10417. {
  10418. if (func_num_args() === 0) {
  10419. throw new \InvalidArgumentException('Missing argument(s) when calling unshift');
  10420. }
  10421. $spec = func_get_args();
  10422. $this->specs->unshift($spec);
  10423. return $this;
  10424. }
  10425. public function push()
  10426. {
  10427. if (func_num_args() === 0) {
  10428. throw new \InvalidArgumentException('Missing argument(s) when calling push');
  10429. }
  10430. $spec = func_get_args();
  10431. $this->specs->push($spec);
  10432. return $this;
  10433. }
  10434. public function resolve(HttpKernelInterface $app)
  10435. {
  10436. $middlewares = array($app);
  10437. foreach ($this->specs as $spec) {
  10438. $args = $spec;
  10439. $firstArg = array_shift($args);
  10440. if (is_callable($firstArg)) {
  10441. $app = $firstArg($app);
  10442. } else {
  10443. $kernelClass = $firstArg;
  10444. array_unshift($args, $app);
  10445. $reflection = new \ReflectionClass($kernelClass);
  10446. $app = $reflection->newInstanceArgs($args);
  10447. }
  10448. array_unshift($middlewares, $app);
  10449. }
  10450. return new StackedHttpKernel($app, $middlewares);
  10451. }
  10452. }
  10453. namespace Stack;
  10454. use Symfony\Component\HttpKernel\HttpKernelInterface;
  10455. use Symfony\Component\HttpKernel\TerminableInterface;
  10456. use Symfony\Component\HttpFoundation\Request;
  10457. use Symfony\Component\HttpFoundation\Response;
  10458. class StackedHttpKernel implements HttpKernelInterface, TerminableInterface
  10459. {
  10460. private $app;
  10461. private $middlewares = array();
  10462. public function __construct(HttpKernelInterface $app, array $middlewares)
  10463. {
  10464. $this->app = $app;
  10465. $this->middlewares = $middlewares;
  10466. }
  10467. public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
  10468. {
  10469. return $this->app->handle($request, $type, $catch);
  10470. }
  10471. public function terminate(Request $request, Response $response)
  10472. {
  10473. foreach ($this->middlewares as $kernel) {
  10474. if ($kernel instanceof TerminableInterface) {
  10475. $kernel->terminate($request, $response);
  10476. }
  10477. }
  10478. }
  10479. }