Commit 6b165791 by 杨树贤

添加redis拓展

parent 908d1549
Showing with 1 additions and 4901 deletions
common @ 6a492b76
Subproject commit cf58bc38ef8bdea9369a73ad4cb0d4118328586d
Subproject commit 6a492b76f3938205ed9d94cd12b81d66feea657d
<?php
namespace Illuminate\Routing\Console;
use Illuminate\Support\Str;
use InvalidArgumentException;
use Illuminate\Console\GeneratorCommand;
use Symfony\Component\Console\Input\InputOption;
class ControllerMakeCommand extends GeneratorCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:controller';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new controller class';
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Controller';
/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
if ($this->option('parent')) {
return __DIR__.'/stubs/controller.nested.stub';
} elseif ($this->option('model')) {
return __DIR__.'/stubs/controller.model.stub';
} elseif ($this->option('resource')) {
return __DIR__.'/stubs/controller.stub';
}
return __DIR__.'/stubs/controller.plain.stub';
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Http\Controllers';
}
/**
* Build the class with the given name.
*
* Remove the base controller import if we are already in base namespace.
*
* @param string $name
* @return string
*/
protected function buildClass($name)
{
$controllerNamespace = $this->getNamespace($name);
$replace = [];
if ($this->option('parent')) {
$replace = $this->buildParentReplacements();
}
if ($this->option('model')) {
$replace = $this->buildModelReplacements($replace);
}
$replace["use {$controllerNamespace}\Controller;\n"] = '';
return str_replace(
array_keys($replace), array_values($replace), parent::buildClass($name)
);
}
/**
* Build the replacements for a parent controller.
*
* @return array
*/
protected function buildParentReplacements()
{
$parentModelClass = $this->parseModel($this->option('parent'));
if (! class_exists($parentModelClass)) {
if ($this->confirm("A {$parentModelClass} model does not exist. Do you want to generate it?", true)) {
$this->call('make:model', ['name' => $parentModelClass]);
}
}
return [
'ParentDummyFullModelClass' => $parentModelClass,
'ParentDummyModelClass' => class_basename($parentModelClass),
'ParentDummyModelVariable' => lcfirst(class_basename($parentModelClass)),
];
}
/**
* Build the model replacement values.
*
* @param array $replace
* @return array
*/
protected function buildModelReplacements(array $replace)
{
$modelClass = $this->parseModel($this->option('model'));
if (! class_exists($modelClass)) {
if ($this->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) {
$this->call('make:model', ['name' => $modelClass]);
}
}
return array_merge($replace, [
'DummyFullModelClass' => $modelClass,
'DummyModelClass' => class_basename($modelClass),
'DummyModelVariable' => lcfirst(class_basename($modelClass)),
]);
}
/**
* Get the fully-qualified model class name.
*
* @param string $model
* @return string
*/
protected function parseModel($model)
{
if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) {
throw new InvalidArgumentException('Model name contains invalid characters.');
}
$model = trim(str_replace('/', '\\', $model), '\\');
if (! Str::startsWith($model, $rootNamespace = $this->laravel->getNamespace())) {
$model = $rootNamespace.$model;
}
return $model;
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [
['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model.'],
['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class.'],
['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class.'],
];
}
}
<?php
namespace Illuminate\Routing\Console;
use Illuminate\Console\GeneratorCommand;
class MiddlewareMakeCommand extends GeneratorCommand
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:middleware';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new middleware class';
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Middleware';
/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
return __DIR__.'/stubs/middleware.stub';
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Http\Middleware';
}
}
<?php
namespace DummyNamespace;
use DummyFullModelClass;
use Illuminate\Http\Request;
use DummyRootNamespaceHttp\Controllers\Controller;
class DummyClass extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function show(DummyModelClass $DummyModelVariable)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function edit(DummyModelClass $DummyModelVariable)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function update(Request $request, DummyModelClass $DummyModelVariable)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function destroy(DummyModelClass $DummyModelVariable)
{
//
}
}
<?php
namespace DummyNamespace;
use DummyFullModelClass;
use ParentDummyFullModelClass;
use Illuminate\Http\Request;
use DummyRootNamespaceHttp\Controllers\Controller;
class DummyClass extends Controller
{
/**
* Display a listing of the resource.
*
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @return \Illuminate\Http\Response
*/
public function index(ParentDummyModelClass $ParentDummyModelVariable)
{
//
}
/**
* Show the form for creating a new resource.
*
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @return \Illuminate\Http\Response
*/
public function create(ParentDummyModelClass $ParentDummyModelVariable)
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @return \Illuminate\Http\Response
*/
public function store(Request $request, ParentDummyModelClass $ParentDummyModelVariable)
{
//
}
/**
* Display the specified resource.
*
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function show(ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function edit(ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function update(Request $request, ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
* @param \DummyFullModelClass $DummyModelVariable
* @return \Illuminate\Http\Response
*/
public function destroy(ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
{
//
}
}
<?php
namespace DummyNamespace;
use Illuminate\Http\Request;
use DummyRootNamespaceHttp\Controllers\Controller;
class DummyClass extends Controller
{
//
}
<?php
namespace DummyNamespace;
use Illuminate\Http\Request;
use DummyRootNamespaceHttp\Controllers\Controller;
class DummyClass extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
<?php
namespace DummyNamespace;
use Closure;
class DummyClass
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
}
<?php
namespace Illuminate\Routing\Contracts;
use Illuminate\Routing\Route;
interface ControllerDispatcher
{
/**
* Dispatch a request to a given controller and method.
*
* @param \Illuminate\Routing\Route $route
* @param mixed $controller
* @param string $method
* @return mixed
*/
public function dispatch(Route $route, $controller, $method);
/**
* Get the middleware for the controller instance.
*
* @param \Illuminate\Routing\Controller $controller
* @param string $method
* @return array
*/
public function getMiddleware($controller, $method);
}
<?php
namespace Illuminate\Routing;
use BadMethodCallException;
abstract class Controller
{
/**
* The middleware registered on the controller.
*
* @var array
*/
protected $middleware = [];
/**
* Register middleware on the controller.
*
* @param array|string|\Closure $middleware
* @param array $options
* @return \Illuminate\Routing\ControllerMiddlewareOptions
*/
public function middleware($middleware, array $options = [])
{
foreach ((array) $middleware as $m) {
$this->middleware[] = [
'middleware' => $m,
'options' => &$options,
];
}
return new ControllerMiddlewareOptions($options);
}
/**
* Get the middleware assigned to the controller.
*
* @return array
*/
public function getMiddleware()
{
return $this->middleware;
}
/**
* Execute an action on the controller.
*
* @param string $method
* @param array $parameters
* @return \Symfony\Component\HttpFoundation\Response
*/
public function callAction($method, $parameters)
{
return call_user_func_array([$this, $method], $parameters);
}
/**
* Handle calls to missing methods on the controller.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
throw new BadMethodCallException("Method [{$method}] does not exist on [".get_class($this).'].');
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Container\Container;
use Illuminate\Routing\Contracts\ControllerDispatcher as ControllerDispatcherContract;
class ControllerDispatcher implements ControllerDispatcherContract
{
use RouteDependencyResolverTrait;
/**
* The container instance.
*
* @var \Illuminate\Container\Container
*/
protected $container;
/**
* Create a new controller dispatcher instance.
*
* @param \Illuminate\Container\Container $container
* @return void
*/
public function __construct(Container $container)
{
$this->container = $container;
}
/**
* Dispatch a request to a given controller and method.
*
* @param \Illuminate\Routing\Route $route
* @param mixed $controller
* @param string $method
* @return mixed
*/
public function dispatch(Route $route, $controller, $method)
{
$parameters = $this->resolveClassMethodDependencies(
$route->parametersWithoutNulls(), $controller, $method
);
if (method_exists($controller, 'callAction')) {
return $controller->callAction($method, $parameters);
}
return $controller->{$method}(...array_values($parameters));
}
/**
* Get the middleware for the controller instance.
*
* @param \Illuminate\Routing\Controller $controller
* @param string $method
* @return array
*/
public function getMiddleware($controller, $method)
{
if (! method_exists($controller, 'getMiddleware')) {
return [];
}
return collect($controller->getMiddleware())->reject(function ($data) use ($method) {
return static::methodExcludedByOptions($method, $data['options']);
})->pluck('middleware')->all();
}
/**
* Determine if the given options exclude a particular method.
*
* @param string $method
* @param array $options
* @return bool
*/
protected static function methodExcludedByOptions($method, array $options)
{
return (isset($options['only']) && ! in_array($method, (array) $options['only'])) ||
(! empty($options['except']) && in_array($method, (array) $options['except']));
}
}
<?php
namespace Illuminate\Routing;
class ControllerMiddlewareOptions
{
/**
* The middleware options.
*
* @var array
*/
protected $options;
/**
* Create a new middleware option instance.
*
* @param array $options
* @return void
*/
public function __construct(array &$options)
{
$this->options = &$options;
}
/**
* Set the controller methods the middleware should apply to.
*
* @param array|string|dynamic $methods
* @return $this
*/
public function only($methods)
{
$this->options['only'] = is_array($methods) ? $methods : func_get_args();
return $this;
}
/**
* Set the controller methods the middleware should exclude.
*
* @param array|string|dynamic $methods
* @return $this
*/
public function except($methods)
{
$this->options['except'] = is_array($methods) ? $methods : func_get_args();
return $this;
}
}
<?php
namespace Illuminate\Routing\Events;
class RouteMatched
{
/**
* The route instance.
*
* @var \Illuminate\Routing\Route
*/
public $route;
/**
* The request instance.
*
* @var \Illuminate\Http\Request
*/
public $request;
/**
* Create a new event instance.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return void
*/
public function __construct($route, $request)
{
$this->route = $route;
$this->request = $request;
}
}
<?php
namespace Illuminate\Routing\Exceptions;
use Exception;
class UrlGenerationException extends Exception
{
/**
* Create a new exception for missing route parameters.
*
* @param \Illuminate\Routing\Route $route
* @return static
*/
public static function forMissingParameters($route)
{
return new static("Missing required parameters for [Route: {$route->getName()}] [URI: {$route->uri()}].");
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Str;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class ImplicitRouteBinding
{
/**
* Resolve the implicit route bindings for the given route.
*
* @param \Illuminate\Container\Container $container
* @param \Illuminate\Routing\Route $route
* @return void
*/
public static function resolveForRoute($container, $route)
{
$parameters = $route->parameters();
foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) {
if (! $parameterName = static::getParameterName($parameter->name, $parameters)) {
continue;
}
$parameterValue = $parameters[$parameterName];
if ($parameterValue instanceof UrlRoutable) {
continue;
}
$instance = $container->make($parameter->getClass()->name);
if (! $model = $instance->resolveRouteBinding($parameterValue)) {
throw (new ModelNotFoundException)->setModel(get_class($instance));
}
$route->setParameter($parameterName, $model);
}
}
/**
* Return the parameter name if it exists in the given parameters.
*
* @param string $name
* @param array $parameters
* @return string|null
*/
protected static function getParameterName($name, $parameters)
{
if (array_key_exists($name, $parameters)) {
return $name;
}
if (array_key_exists($snakedName = Str::snake($name), $parameters)) {
return $snakedName;
}
}
}
<?php
namespace Illuminate\Routing\Matching;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
class HostValidator implements ValidatorInterface
{
/**
* Validate a given rule against a route and request.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return bool
*/
public function matches(Route $route, Request $request)
{
if (is_null($route->getCompiled()->getHostRegex())) {
return true;
}
return preg_match($route->getCompiled()->getHostRegex(), $request->getHost());
}
}
<?php
namespace Illuminate\Routing\Matching;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
class MethodValidator implements ValidatorInterface
{
/**
* Validate a given rule against a route and request.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return bool
*/
public function matches(Route $route, Request $request)
{
return in_array($request->getMethod(), $route->methods());
}
}
<?php
namespace Illuminate\Routing\Matching;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
class SchemeValidator implements ValidatorInterface
{
/**
* Validate a given rule against a route and request.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return bool
*/
public function matches(Route $route, Request $request)
{
if ($route->httpOnly()) {
return ! $request->secure();
} elseif ($route->secure()) {
return $request->secure();
}
return true;
}
}
<?php
namespace Illuminate\Routing\Matching;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
class UriValidator implements ValidatorInterface
{
/**
* Validate a given rule against a route and request.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return bool
*/
public function matches(Route $route, Request $request)
{
$path = $request->path() == '/' ? '/' : '/'.$request->path();
return preg_match($route->getCompiled()->getRegex(), rawurldecode($path));
}
}
<?php
namespace Illuminate\Routing\Matching;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
interface ValidatorInterface
{
/**
* Validate a given rule against a route and request.
*
* @param \Illuminate\Routing\Route $route
* @param \Illuminate\Http\Request $request
* @return bool
*/
public function matches(Route $route, Request $request);
}
<?php
namespace Illuminate\Routing\Middleware;
use Closure;
use Illuminate\Contracts\Routing\Registrar;
class SubstituteBindings
{
/**
* The router instance.
*
* @var \Illuminate\Contracts\Routing\Registrar
*/
protected $router;
/**
* Create a new bindings substitutor.
*
* @param \Illuminate\Contracts\Routing\Registrar $router
* @return void
*/
public function __construct(Registrar $router)
{
$this->router = $router;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$this->router->substituteBindings($route = $request->route());
$this->router->substituteImplicitBindings($route);
return $next($request);
}
}
<?php
namespace Illuminate\Routing\Middleware;
use Closure;
use RuntimeException;
use Illuminate\Support\Str;
use Illuminate\Cache\RateLimiter;
use Illuminate\Support\InteractsWithTime;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
class ThrottleRequests
{
use InteractsWithTime;
/**
* The rate limiter instance.
*
* @var \Illuminate\Cache\RateLimiter
*/
protected $limiter;
/**
* Create a new request throttler.
*
* @param \Illuminate\Cache\RateLimiter $limiter
* @return void
*/
public function __construct(RateLimiter $limiter)
{
$this->limiter = $limiter;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int|string $maxAttempts
* @param float|int $decayMinutes
* @return mixed
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
{
$key = $this->resolveRequestSignature($request);
$maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);
if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
throw $this->buildException($key, $maxAttempts);
}
$this->limiter->hit($key, $decayMinutes);
$response = $next($request);
return $this->addHeaders(
$response, $maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts)
);
}
/**
* Resolve the number of attempts if the user is authenticated or not.
*
* @param \Illuminate\Http\Request $request
* @param int|string $maxAttempts
* @return int
*/
protected function resolveMaxAttempts($request, $maxAttempts)
{
if (Str::contains($maxAttempts, '|')) {
$maxAttempts = explode('|', $maxAttempts, 2)[$request->user() ? 1 : 0];
}
return (int) $maxAttempts;
}
/**
* Resolve request signature.
*
* @param \Illuminate\Http\Request $request
* @return string
* @throws \RuntimeException
*/
protected function resolveRequestSignature($request)
{
if ($user = $request->user()) {
return sha1($user->getAuthIdentifier());
}
if ($route = $request->route()) {
return sha1($route->getDomain().'|'.$request->ip());
}
throw new RuntimeException(
'Unable to generate the request signature. Route unavailable.'
);
}
/**
* Create a 'too many attempts' exception.
*
* @param string $key
* @param int $maxAttempts
* @return \Symfony\Component\HttpKernel\Exception\HttpException
*/
protected function buildException($key, $maxAttempts)
{
$retryAfter = $this->getTimeUntilNextRetry($key);
$headers = $this->getHeaders(
$maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
$retryAfter
);
return new HttpException(
429, 'Too Many Attempts.', null, $headers
);
}
/**
* Get the number of seconds until the next retry.
*
* @param string $key
* @return int
*/
protected function getTimeUntilNextRetry($key)
{
return $this->limiter->availableIn($key);
}
/**
* Add the limit header information to the given response.
*
* @param \Symfony\Component\HttpFoundation\Response $response
* @param int $maxAttempts
* @param int $remainingAttempts
* @param int|null $retryAfter
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function addHeaders(Response $response, $maxAttempts, $remainingAttempts, $retryAfter = null)
{
$response->headers->add(
$this->getHeaders($maxAttempts, $remainingAttempts, $retryAfter)
);
return $response;
}
/**
* Get the limit headers information.
*
* @param int $maxAttempts
* @param int $remainingAttempts
* @param int|null $retryAfter
* @return array
*/
protected function getHeaders($maxAttempts, $remainingAttempts, $retryAfter = null)
{
$headers = [
'X-RateLimit-Limit' => $maxAttempts,
'X-RateLimit-Remaining' => $remainingAttempts,
];
if (! is_null($retryAfter)) {
$headers['Retry-After'] = $retryAfter;
$headers['X-RateLimit-Reset'] = $this->availableAt($retryAfter);
}
return $headers;
}
/**
* Calculate the number of remaining attempts.
*
* @param string $key
* @param int $maxAttempts
* @param int|null $retryAfter
* @return int
*/
protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null)
{
if (is_null($retryAfter)) {
return $this->limiter->retriesLeft($key, $maxAttempts);
}
return 0;
}
}
<?php
namespace Illuminate\Routing\Middleware;
use Closure;
use Illuminate\Redis\Limiters\DurationLimiter;
use Illuminate\Contracts\Redis\Factory as Redis;
class ThrottleRequestsWithRedis extends ThrottleRequests
{
/**
* The Redis factory implementation.
*
* @var \Illuminate\Contracts\Redis\Factory
*/
protected $redis;
/**
* The timestamp of the end of the current duration.
*
* @var int
*/
public $decaysAt;
/**
* The number of remaining slots.
*
* @var int
*/
public $remaining;
/**
* Create a new request throttler.
*
* @param \Illuminate\Contracts\Redis\Factory $redis
* @return void
*/
public function __construct(Redis $redis)
{
$this->redis = $redis;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param int|string $maxAttempts
* @param float|int $decayMinutes
* @return mixed
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
{
$key = $this->resolveRequestSignature($request);
$maxAttempts = $this->resolveMaxAttempts($request, $maxAttempts);
if ($this->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
throw $this->buildException($key, $maxAttempts);
}
$response = $next($request);
return $this->addHeaders(
$response, $maxAttempts,
$this->calculateRemainingAttempts($key, $maxAttempts)
);
}
/**
* Determine if the given key has been "accessed" too many times.
*
* @param string $key
* @param int $maxAttempts
* @param int $decayMinutes
* @return mixed
*/
protected function tooManyAttempts($key, $maxAttempts, $decayMinutes)
{
$limiter = new DurationLimiter(
$this->redis, $key, $maxAttempts, $decayMinutes * 60
);
return tap(! $limiter->acquire(), function () use ($limiter) {
list($this->decaysAt, $this->remaining) = [
$limiter->decaysAt, $limiter->remaining,
];
});
}
/**
* Calculate the number of remaining attempts.
*
* @param string $key
* @param int $maxAttempts
* @param int|null $retryAfter
* @return int
*/
protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null)
{
if (is_null($retryAfter)) {
return $this->remaining;
}
return 0;
}
/**
* Get the number of seconds until the lock is released.
*
* @param string $key
* @return int
*/
protected function getTimeUntilNextRetry($key)
{
return $this->decaysAt - $this->currentTime();
}
}
<?php
namespace Illuminate\Routing;
use Closure;
class MiddlewareNameResolver
{
/**
* Resolve the middleware name to a class name(s) preserving passed parameters.
*
* @param string $name
* @param array $map
* @param array $middlewareGroups
* @return \Closure|string|array
*/
public static function resolve($name, $map, $middlewareGroups)
{
// When the middleware is simply a Closure, we will return this Closure instance
// directly so that Closures can be registered as middleware inline, which is
// convenient on occasions when the developers are experimenting with them.
if ($name instanceof Closure) {
return $name;
}
if (isset($map[$name]) && $map[$name] instanceof Closure) {
return $map[$name];
}
// If the middleware is the name of a middleware group, we will return the array
// of middlewares that belong to the group. This allows developers to group a
// set of middleware under single keys that can be conveniently referenced.
if (isset($middlewareGroups[$name])) {
return static::parseMiddlewareGroup($name, $map, $middlewareGroups);
}
// Finally, when the middleware is simply a string mapped to a class name the
// middleware name will get parsed into the full class name and parameters
// which may be run using the Pipeline which accepts this string format.
list($name, $parameters) = array_pad(explode(':', $name, 2), 2, null);
return ($map[$name] ?? $name).(! is_null($parameters) ? ':'.$parameters : '');
}
/**
* Parse the middleware group and format it for usage.
*
* @param string $name
* @param array $map
* @param array $middlewareGroups
* @return array
*/
protected static function parseMiddlewareGroup($name, $map, $middlewareGroups)
{
$results = [];
foreach ($middlewareGroups[$name] as $middleware) {
// If the middleware is another middleware group we will pull in the group and
// merge its middleware into the results. This allows groups to conveniently
// reference other groups without needing to repeat all their middlewares.
if (isset($middlewareGroups[$middleware])) {
$results = array_merge($results, static::parseMiddlewareGroup(
$middleware, $map, $middlewareGroups
));
continue;
}
list($middleware, $parameters) = array_pad(
explode(':', $middleware, 2), 2, null
);
// If this middleware is actually a route middleware, we will extract the full
// class name out of the middleware list now. Then we'll add the parameters
// back onto this class' name so the pipeline will properly extract them.
if (isset($map[$middleware])) {
$middleware = $map[$middleware];
}
$results[] = $middleware.($parameters ? ':'.$parameters : '');
}
return $results;
}
}
<?php
namespace Illuminate\Routing;
class PendingResourceRegistration
{
/**
* The resource registrar.
*
* @var \Illuminate\Routing\ResourceRegistrar
*/
protected $registrar;
/**
* The resource name.
*
* @var string
*/
protected $name;
/**
* The resource controller.
*
* @var string
*/
protected $controller;
/**
* The resource options.
*
* @var array
*/
protected $options = [];
/**
* Create a new pending resource registration instance.
*
* @param \Illuminate\Routing\ResourceRegistrar $registrar
* @param string $name
* @param string $controller
* @param array $options
* @return void
*/
public function __construct(ResourceRegistrar $registrar, $name, $controller, array $options)
{
$this->name = $name;
$this->options = $options;
$this->registrar = $registrar;
$this->controller = $controller;
}
/**
* Set the methods the controller should apply to.
*
* @param array|string|dynamic $methods
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function only($methods)
{
$this->options['only'] = is_array($methods) ? $methods : func_get_args();
return $this;
}
/**
* Set the methods the controller should exclude.
*
* @param array|string|dynamic $methods
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function except($methods)
{
$this->options['except'] = is_array($methods) ? $methods : func_get_args();
return $this;
}
/**
* Set the route names for controller actions.
*
* @param array|string $names
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function names($names)
{
$this->options['names'] = $names;
return $this;
}
/**
* Set the route name for a controller action.
*
* @param string $method
* @param string $name
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function name($method, $name)
{
$this->options['names'][$method] = $name;
return $this;
}
/**
* Override the route parameter names.
*
* @param array|string $parameters
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function parameters($parameters)
{
$this->options['parameters'] = $parameters;
return $this;
}
/**
* Override a route parameter's name.
*
* @param string $previous
* @param string $new
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function parameter($previous, $new)
{
$this->options['parameters'][$previous] = $new;
return $this;
}
/**
* Set a middleware to the resource.
*
* @param mixed $middleware
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function middleware($middleware)
{
$this->options['middleware'] = $middleware;
return $this;
}
/**
* Handle the object's destruction.
*
* @return void
*/
public function __destruct()
{
$this->registrar->register($this->name, $this->controller, $this->options);
}
}
<?php
namespace Illuminate\Routing;
use Closure;
use Exception;
use Throwable;
use Illuminate\Http\Request;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Pipeline\Pipeline as BasePipeline;
use Symfony\Component\Debug\Exception\FatalThrowableError;
/**
* This extended pipeline catches any exceptions that occur during each slice.
*
* The exceptions are converted to HTTP responses for proper middleware handling.
*/
class Pipeline extends BasePipeline
{
/**
* Get the final piece of the Closure onion.
*
* @param \Closure $destination
* @return \Closure
*/
protected function prepareDestination(Closure $destination)
{
return function ($passable) use ($destination) {
try {
return $destination($passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
}
/**
* Get a Closure that represents a slice of the application onion.
*
* @return \Closure
*/
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
try {
$slice = parent::carry();
$callable = $slice($stack, $pipe);
return $callable($passable);
} catch (Exception $e) {
return $this->handleException($passable, $e);
} catch (Throwable $e) {
return $this->handleException($passable, new FatalThrowableError($e));
}
};
};
}
/**
* Handle the given exception.
*
* @param mixed $passable
* @param \Exception $e
* @return mixed
*
* @throws \Exception
*/
protected function handleException($passable, Exception $e)
{
if (! $this->container->bound(ExceptionHandler::class) ||
! $passable instanceof Request) {
throw $e;
}
$handler = $this->container->make(ExceptionHandler::class);
$handler->report($e);
$response = $handler->render($passable, $e);
if (method_exists($response, 'withException')) {
$response->withException($e);
}
return $response;
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Http\RedirectResponse;
class RedirectController extends Controller
{
/**
* Invoke the controller method.
*
* @param array $args
* @return \Illuminate\Http\RedirectResponse
*/
public function __invoke(...$args)
{
list($destination, $status) = array_slice($args, -2);
return new RedirectResponse($destination, $status);
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Session\Store as SessionStore;
class Redirector
{
use Macroable;
/**
* The URL generator instance.
*
* @var \Illuminate\Routing\UrlGenerator
*/
protected $generator;
/**
* The session store instance.
*
* @var \Illuminate\Session\Store
*/
protected $session;
/**
* Create a new Redirector instance.
*
* @param \Illuminate\Routing\UrlGenerator $generator
* @return void
*/
public function __construct(UrlGenerator $generator)
{
$this->generator = $generator;
}
/**
* Create a new redirect response to the "home" route.
*
* @param int $status
* @return \Illuminate\Http\RedirectResponse
*/
public function home($status = 302)
{
return $this->to($this->generator->route('home'), $status);
}
/**
* Create a new redirect response to the previous location.
*
* @param int $status
* @param array $headers
* @param mixed $fallback
* @return \Illuminate\Http\RedirectResponse
*/
public function back($status = 302, $headers = [], $fallback = false)
{
return $this->createRedirect($this->generator->previous($fallback), $status, $headers);
}
/**
* Create a new redirect response to the current URI.
*
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function refresh($status = 302, $headers = [])
{
return $this->to($this->generator->getRequest()->path(), $status, $headers);
}
/**
* Create a new redirect response, while putting the current URL in the session.
*
* @param string $path
* @param int $status
* @param array $headers
* @param bool $secure
* @return \Illuminate\Http\RedirectResponse
*/
public function guest($path, $status = 302, $headers = [], $secure = null)
{
$this->session->put('url.intended', $this->generator->full());
return $this->to($path, $status, $headers, $secure);
}
/**
* Create a new redirect response to the previously intended location.
*
* @param string $default
* @param int $status
* @param array $headers
* @param bool $secure
* @return \Illuminate\Http\RedirectResponse
*/
public function intended($default = '/', $status = 302, $headers = [], $secure = null)
{
$path = $this->session->pull('url.intended', $default);
return $this->to($path, $status, $headers, $secure);
}
/**
* Create a new redirect response to the given path.
*
* @param string $path
* @param int $status
* @param array $headers
* @param bool $secure
* @return \Illuminate\Http\RedirectResponse
*/
public function to($path, $status = 302, $headers = [], $secure = null)
{
return $this->createRedirect($this->generator->to($path, [], $secure), $status, $headers);
}
/**
* Create a new redirect response to an external URL (no validation).
*
* @param string $path
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function away($path, $status = 302, $headers = [])
{
return $this->createRedirect($path, $status, $headers);
}
/**
* Create a new redirect response to the given HTTPS path.
*
* @param string $path
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function secure($path, $status = 302, $headers = [])
{
return $this->to($path, $status, $headers, true);
}
/**
* Create a new redirect response to a named route.
*
* @param string $route
* @param array $parameters
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function route($route, $parameters = [], $status = 302, $headers = [])
{
return $this->to($this->generator->route($route, $parameters), $status, $headers);
}
/**
* Create a new redirect response to a controller action.
*
* @param string $action
* @param array $parameters
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function action($action, $parameters = [], $status = 302, $headers = [])
{
return $this->to($this->generator->action($action, $parameters), $status, $headers);
}
/**
* Create a new redirect response.
*
* @param string $path
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
protected function createRedirect($path, $status, $headers)
{
return tap(new RedirectResponse($path, $status, $headers), function ($redirect) {
if (isset($this->session)) {
$redirect->setSession($this->session);
}
$redirect->setRequest($this->generator->getRequest());
});
}
/**
* Get the URL generator instance.
*
* @return \Illuminate\Routing\UrlGenerator
*/
public function getUrlGenerator()
{
return $this->generator;
}
/**
* Set the active session store.
*
* @param \Illuminate\Session\Store $session
* @return void
*/
public function setSession(SessionStore $session)
{
$this->session = $session;
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Str;
use Illuminate\Http\Response;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Traits\Macroable;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Illuminate\Contracts\Routing\ResponseFactory as FactoryContract;
class ResponseFactory implements FactoryContract
{
use Macroable;
/**
* The view factory instance.
*
* @var \Illuminate\Contracts\View\Factory
*/
protected $view;
/**
* The redirector instance.
*
* @var \Illuminate\Routing\Redirector
*/
protected $redirector;
/**
* Create a new response factory instance.
*
* @param \Illuminate\Contracts\View\Factory $view
* @param \Illuminate\Routing\Redirector $redirector
* @return void
*/
public function __construct(ViewFactory $view, Redirector $redirector)
{
$this->view = $view;
$this->redirector = $redirector;
}
/**
* Return a new response from the application.
*
* @param string $content
* @param int $status
* @param array $headers
* @return \Illuminate\Http\Response
*/
public function make($content = '', $status = 200, array $headers = [])
{
return new Response($content, $status, $headers);
}
/**
* Return a new view response from the application.
*
* @param string $view
* @param array $data
* @param int $status
* @param array $headers
* @return \Illuminate\Http\Response
*/
public function view($view, $data = [], $status = 200, array $headers = [])
{
return $this->make($this->view->make($view, $data), $status, $headers);
}
/**
* Return a new JSON response from the application.
*
* @param mixed $data
* @param int $status
* @param array $headers
* @param int $options
* @return \Illuminate\Http\JsonResponse
*/
public function json($data = [], $status = 200, array $headers = [], $options = 0)
{
return new JsonResponse($data, $status, $headers, $options);
}
/**
* Return a new JSONP response from the application.
*
* @param string $callback
* @param mixed $data
* @param int $status
* @param array $headers
* @param int $options
* @return \Illuminate\Http\JsonResponse
*/
public function jsonp($callback, $data = [], $status = 200, array $headers = [], $options = 0)
{
return $this->json($data, $status, $headers, $options)->setCallback($callback);
}
/**
* Return a new streamed response from the application.
*
* @param \Closure $callback
* @param int $status
* @param array $headers
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public function stream($callback, $status = 200, array $headers = [])
{
return new StreamedResponse($callback, $status, $headers);
}
/**
* Create a new file download response.
*
* @param \SplFileInfo|string $file
* @param string $name
* @param array $headers
* @param string|null $disposition
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function download($file, $name = null, array $headers = [], $disposition = 'attachment')
{
$response = new BinaryFileResponse($file, 200, $headers, true, $disposition);
if (! is_null($name)) {
return $response->setContentDisposition($disposition, $name, str_replace('%', '', Str::ascii($name)));
}
return $response;
}
/**
* Return the raw contents of a binary file.
*
* @param \SplFileInfo|string $file
* @param array $headers
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function file($file, array $headers = [])
{
return new BinaryFileResponse($file, 200, $headers);
}
/**
* Create a new redirect response to the given path.
*
* @param string $path
* @param int $status
* @param array $headers
* @param bool|null $secure
* @return \Illuminate\Http\RedirectResponse
*/
public function redirectTo($path, $status = 302, $headers = [], $secure = null)
{
return $this->redirector->to($path, $status, $headers, $secure);
}
/**
* Create a new redirect response to a named route.
*
* @param string $route
* @param array $parameters
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function redirectToRoute($route, $parameters = [], $status = 302, $headers = [])
{
return $this->redirector->route($route, $parameters, $status, $headers);
}
/**
* Create a new redirect response to a controller action.
*
* @param string $action
* @param array $parameters
* @param int $status
* @param array $headers
* @return \Illuminate\Http\RedirectResponse
*/
public function redirectToAction($action, $parameters = [], $status = 302, $headers = [])
{
return $this->redirector->action($action, $parameters, $status, $headers);
}
/**
* Create a new redirect response, while putting the current URL in the session.
*
* @param string $path
* @param int $status
* @param array $headers
* @param bool|null $secure
* @return \Illuminate\Http\RedirectResponse
*/
public function redirectGuest($path, $status = 302, $headers = [], $secure = null)
{
return $this->redirector->guest($path, $status, $headers, $secure);
}
/**
* Create a new redirect response to the previously intended location.
*
* @param string $default
* @param int $status
* @param array $headers
* @param bool|null $secure
* @return \Illuminate\Http\RedirectResponse
*/
public function redirectToIntended($default = '/', $status = 302, $headers = [], $secure = null)
{
return $this->redirector->intended($default, $status, $headers, $secure);
}
}
<?php
namespace Illuminate\Routing;
use LogicException;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use UnexpectedValueException;
class RouteAction
{
/**
* Parse the given action into an array.
*
* @param string $uri
* @param mixed $action
* @return array
*/
public static function parse($uri, $action)
{
// If no action is passed in right away, we assume the user will make use of
// fluent routing. In that case, we set a default closure, to be executed
// if the user never explicitly sets an action to handle the given uri.
if (is_null($action)) {
return static::missingAction($uri);
}
// If the action is already a Closure instance, we will just set that instance
// as the "uses" property, because there is nothing else we need to do when
// it is available. Otherwise we will need to find it in the action list.
if (is_callable($action)) {
return ['uses' => $action];
}
// If no "uses" property has been set, we will dig through the array to find a
// Closure instance within this list. We will set the first Closure we come
// across into the "uses" property that will get fired off by this route.
elseif (! isset($action['uses'])) {
$action['uses'] = static::findCallable($action);
}
if (is_string($action['uses']) && ! Str::contains($action['uses'], '@')) {
$action['uses'] = static::makeInvokable($action['uses']);
}
return $action;
}
/**
* Get an action for a route that has no action.
*
* @param string $uri
* @return array
*/
protected static function missingAction($uri)
{
return ['uses' => function () use ($uri) {
throw new LogicException("Route for [{$uri}] has no action.");
}];
}
/**
* Find the callable in an action array.
*
* @param array $action
* @return callable
*/
protected static function findCallable(array $action)
{
return Arr::first($action, function ($value, $key) {
return is_callable($value) && is_numeric($key);
});
}
/**
* Make an action for an invokable controller.
*
* @param string $action
* @return string
*/
protected static function makeInvokable($action)
{
if (! method_exists($action, '__invoke')) {
throw new UnexpectedValueException("Invalid route action: [{$action}].");
}
return $action.'@__invoke';
}
}
<?php
namespace Illuminate\Routing;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class RouteBinding
{
/**
* Create a Route model binding for a given callback.
*
* @param \Illuminate\Container\Container $container
* @param \Closure|string $binder
* @return \Closure
*/
public static function forCallback($container, $binder)
{
if (is_string($binder)) {
return static::createClassBinding($container, $binder);
}
return $binder;
}
/**
* Create a class based binding using the IoC container.
*
* @param \Illuminate\Container\Container $container
* @param string $binding
* @return \Closure
*/
protected static function createClassBinding($container, $binding)
{
return function ($value, $route) use ($container, $binding) {
// If the binding has an @ sign, we will assume it's being used to delimit
// the class name from the bind method name. This allows for bindings
// to run multiple bind methods in a single class for convenience.
list($class, $method) = Str::parseCallback($binding, 'bind');
$callable = [$container->make($class), $method];
return call_user_func($callable, $value, $route);
};
}
/**
* Create a Route model binding for a model.
*
* @param \Illuminate\Container\Container $container
* @param string $class
* @param \Closure|null $callback
* @return \Closure
*/
public static function forModel($container, $class, $callback = null)
{
return function ($value) use ($container, $class, $callback) {
if (is_null($value)) {
return;
}
// For model binders, we will attempt to retrieve the models using the first
// method on the model instance. If we cannot retrieve the models we'll
// throw a not found exception otherwise we will return the instance.
$instance = $container->make($class);
if ($model = $instance->resolveRouteBinding($value)) {
return $model;
}
// If a callback was supplied to the method we will call that to determine
// what we should do when the model is not found. This just gives these
// developer a little greater flexibility to decide what will happen.
if ($callback instanceof Closure) {
return call_user_func($callback, $value);
}
throw (new ModelNotFoundException)->setModel($class);
};
}
}
<?php
namespace Illuminate\Routing;
use Countable;
use ArrayIterator;
use IteratorAggregate;
use Illuminate\Support\Arr;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
class RouteCollection implements Countable, IteratorAggregate
{
/**
* An array of the routes keyed by method.
*
* @var array
*/
protected $routes = [];
/**
* An flattened array of all of the routes.
*
* @var array
*/
protected $allRoutes = [];
/**
* A look-up table of routes by their names.
*
* @var array
*/
protected $nameList = [];
/**
* A look-up table of routes by controller action.
*
* @var array
*/
protected $actionList = [];
/**
* Add a Route instance to the collection.
*
* @param \Illuminate\Routing\Route $route
* @return \Illuminate\Routing\Route
*/
public function add(Route $route)
{
$this->addToCollections($route);
$this->addLookups($route);
return $route;
}
/**
* Add the given route to the arrays of routes.
*
* @param \Illuminate\Routing\Route $route
* @return void
*/
protected function addToCollections($route)
{
$domainAndUri = $route->getDomain().$route->uri();
foreach ($route->methods() as $method) {
$this->routes[$method][$domainAndUri] = $route;
}
$this->allRoutes[$method.$domainAndUri] = $route;
}
/**
* Add the route to any look-up tables if necessary.
*
* @param \Illuminate\Routing\Route $route
* @return void
*/
protected function addLookups($route)
{
// If the route has a name, we will add it to the name look-up table so that we
// will quickly be able to find any route associate with a name and not have
// to iterate through every route every time we need to perform a look-up.
$action = $route->getAction();
if (isset($action['as'])) {
$this->nameList[$action['as']] = $route;
}
// When the route is routing to a controller we will also store the action that
// is used by the route. This will let us reverse route to controllers while
// processing a request and easily generate URLs to the given controllers.
if (isset($action['controller'])) {
$this->addToActionList($action, $route);
}
}
/**
* Add a route to the controller action dictionary.
*
* @param array $action
* @param \Illuminate\Routing\Route $route
* @return void
*/
protected function addToActionList($action, $route)
{
$this->actionList[trim($action['controller'], '\\')] = $route;
}
/**
* Refresh the name look-up table.
*
* This is done in case any names are fluently defined or if routes are overwritten.
*
* @return void
*/
public function refreshNameLookups()
{
$this->nameList = [];
foreach ($this->allRoutes as $route) {
if ($route->getName()) {
$this->nameList[$route->getName()] = $route;
}
}
}
/**
* Refresh the action look-up table.
*
* This is done in case any actions are overwritten with new controllers.
*
* @return void
*/
public function refreshActionLookups()
{
$this->actionList = [];
foreach ($this->allRoutes as $route) {
if (isset($route->getAction()['controller'])) {
$this->addToActionList($route->getAction(), $route);
}
}
}
/**
* Find the first route matching a given request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Routing\Route
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
*/
public function match(Request $request)
{
$routes = $this->get($request->getMethod());
// First, we will see if we can find a matching route for this current request
// method. If we can, great, we can just return it so that it can be called
// by the consumer. Otherwise we will check for routes with another verb.
$route = $this->matchAgainstRoutes($routes, $request);
if (! is_null($route)) {
return $route->bind($request);
}
// If no route was found we will now check if a matching route is specified by
// another HTTP verb. If it is we will need to throw a MethodNotAllowed and
// inform the user agent of which HTTP verb it should use for this route.
$others = $this->checkForAlternateVerbs($request);
if (count($others) > 0) {
return $this->getRouteForMethods($request, $others);
}
throw new NotFoundHttpException;
}
/**
* Determine if a route in the array matches the request.
*
* @param array $routes
* @param \Illuminate\http\Request $request
* @param bool $includingMethod
* @return \Illuminate\Routing\Route|null
*/
protected function matchAgainstRoutes(array $routes, $request, $includingMethod = true)
{
list($fallbacks, $routes) = collect($routes)->partition(function ($route) {
return $route->isFallback;
});
return $routes->merge($fallbacks)->first(function ($value) use ($request, $includingMethod) {
return $value->matches($request, $includingMethod);
});
}
/**
* Determine if any routes match on another HTTP verb.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function checkForAlternateVerbs($request)
{
$methods = array_diff(Router::$verbs, [$request->getMethod()]);
// Here we will spin through all verbs except for the current request verb and
// check to see if any routes respond to them. If they do, we will return a
// proper error response with the correct headers on the response string.
$others = [];
foreach ($methods as $method) {
if (! is_null($this->matchAgainstRoutes($this->get($method), $request, false))) {
$others[] = $method;
}
}
return $others;
}
/**
* Get a route (if necessary) that responds when other available methods are present.
*
* @param \Illuminate\Http\Request $request
* @param array $methods
* @return \Illuminate\Routing\Route
*
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
*/
protected function getRouteForMethods($request, array $methods)
{
if ($request->method() == 'OPTIONS') {
return (new Route('OPTIONS', $request->path(), function () use ($methods) {
return new Response('', 200, ['Allow' => implode(',', $methods)]);
}))->bind($request);
}
$this->methodNotAllowed($methods);
}
/**
* Throw a method not allowed HTTP exception.
*
* @param array $others
* @return void
*
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
*/
protected function methodNotAllowed(array $others)
{
throw new MethodNotAllowedHttpException($others);
}
/**
* Get routes from the collection by method.
*
* @param string|null $method
* @return array
*/
public function get($method = null)
{
return is_null($method) ? $this->getRoutes() : Arr::get($this->routes, $method, []);
}
/**
* Determine if the route collection contains a given named route.
*
* @param string $name
* @return bool
*/
public function hasNamedRoute($name)
{
return ! is_null($this->getByName($name));
}
/**
* Get a route instance by its name.
*
* @param string $name
* @return \Illuminate\Routing\Route|null
*/
public function getByName($name)
{
return $this->nameList[$name] ?? null;
}
/**
* Get a route instance by its controller action.
*
* @param string $action
* @return \Illuminate\Routing\Route|null
*/
public function getByAction($action)
{
return $this->actionList[$action] ?? null;
}
/**
* Get all of the routes in the collection.
*
* @return array
*/
public function getRoutes()
{
return array_values($this->allRoutes);
}
/**
* Get all of the routes keyed by their HTTP verb / method.
*
* @return array
*/
public function getRoutesByMethod()
{
return $this->routes;
}
/**
* Get all of the routes keyed by their name.
*
* @return array
*/
public function getRoutesByName()
{
return $this->nameList;
}
/**
* Get an iterator for the items.
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator($this->getRoutes());
}
/**
* Count the number of items in the collection.
*
* @return int
*/
public function count()
{
return count($this->getRoutes());
}
}
<?php
namespace Illuminate\Routing;
use Symfony\Component\Routing\Route as SymfonyRoute;
class RouteCompiler
{
/**
* The route instance.
*
* @var \Illuminate\Routing\Route
*/
protected $route;
/**
* Create a new Route compiler instance.
*
* @param \Illuminate\Routing\Route $route
* @return void
*/
public function __construct($route)
{
$this->route = $route;
}
/**
* Compile the route.
*
* @return \Symfony\Component\Routing\CompiledRoute
*/
public function compile()
{
$optionals = $this->getOptionalParameters();
$uri = preg_replace('/\{(\w+?)\?\}/', '{$1}', $this->route->uri());
return (
new SymfonyRoute($uri, $optionals, $this->route->wheres, [], $this->route->getDomain() ?: '')
)->compile();
}
/**
* Get the optional parameters for the route.
*
* @return array
*/
protected function getOptionalParameters()
{
preg_match_all('/\{(\w+?)\?\}/', $this->route->uri(), $matches);
return isset($matches[1]) ? array_fill_keys($matches[1], null) : [];
}
}
<?php
namespace Illuminate\Routing;
use ReflectionMethod;
use ReflectionParameter;
use Illuminate\Support\Arr;
use ReflectionFunctionAbstract;
trait RouteDependencyResolverTrait
{
/**
* Resolve the object method's type-hinted dependencies.
*
* @param array $parameters
* @param object $instance
* @param string $method
* @return array
*/
protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
{
if (! method_exists($instance, $method)) {
return $parameters;
}
return $this->resolveMethodDependencies(
$parameters, new ReflectionMethod($instance, $method)
);
}
/**
* Resolve the given method's type-hinted dependencies.
*
* @param array $parameters
* @param \ReflectionFunctionAbstract $reflector
* @return array
*/
public function resolveMethodDependencies(array $parameters, ReflectionFunctionAbstract $reflector)
{
$instanceCount = 0;
$values = array_values($parameters);
foreach ($reflector->getParameters() as $key => $parameter) {
$instance = $this->transformDependency(
$parameter, $parameters
);
if (! is_null($instance)) {
$instanceCount++;
$this->spliceIntoParameters($parameters, $key, $instance);
} elseif (! isset($values[$key - $instanceCount]) &&
$parameter->isDefaultValueAvailable()) {
$this->spliceIntoParameters($parameters, $key, $parameter->getDefaultValue());
}
}
return $parameters;
}
/**
* Attempt to transform the given parameter into a class instance.
*
* @param \ReflectionParameter $parameter
* @param array $parameters
* @return mixed
*/
protected function transformDependency(ReflectionParameter $parameter, $parameters)
{
$class = $parameter->getClass();
// If the parameter has a type-hinted class, we will check to see if it is already in
// the list of parameters. If it is we will just skip it as it is probably a model
// binding and we do not want to mess with those; otherwise, we resolve it here.
if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
return $parameter->isDefaultValueAvailable()
? $parameter->getDefaultValue()
: $this->container->make($class->name);
}
}
/**
* Determine if an object of the given class is in a list of parameters.
*
* @param string $class
* @param array $parameters
* @return bool
*/
protected function alreadyInParameters($class, array $parameters)
{
return ! is_null(Arr::first($parameters, function ($value) use ($class) {
return $value instanceof $class;
}));
}
/**
* Splice the given value into the parameter list.
*
* @param array $parameters
* @param string $offset
* @param mixed $value
* @return void
*/
protected function spliceIntoParameters(array &$parameters, $offset, $value)
{
array_splice(
$parameters, $offset, 0, [$value]
);
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Arr;
class RouteGroup
{
/**
* Merge route groups into a new array.
*
* @param array $new
* @param array $old
* @return array
*/
public static function merge($new, $old)
{
if (isset($new['domain'])) {
unset($old['domain']);
}
$new = array_merge(static::formatAs($new, $old), [
'namespace' => static::formatNamespace($new, $old),
'prefix' => static::formatPrefix($new, $old),
'where' => static::formatWhere($new, $old),
]);
return array_merge_recursive(Arr::except(
$old, ['namespace', 'prefix', 'where', 'as']
), $new);
}
/**
* Format the namespace for the new group attributes.
*
* @param array $new
* @param array $old
* @return string|null
*/
protected static function formatNamespace($new, $old)
{
if (isset($new['namespace'])) {
return isset($old['namespace'])
? trim($old['namespace'], '\\').'\\'.trim($new['namespace'], '\\')
: trim($new['namespace'], '\\');
}
return $old['namespace'] ?? null;
}
/**
* Format the prefix for the new group attributes.
*
* @param array $new
* @param array $old
* @return string|null
*/
protected static function formatPrefix($new, $old)
{
$old = $old['prefix'] ?? null;
return isset($new['prefix']) ? trim($old, '/').'/'.trim($new['prefix'], '/') : $old;
}
/**
* Format the "wheres" for the new group attributes.
*
* @param array $new
* @param array $old
* @return array
*/
protected static function formatWhere($new, $old)
{
return array_merge(
$old['where'] ?? [],
$new['where'] ?? []
);
}
/**
* Format the "as" clause of the new group attributes.
*
* @param array $new
* @param array $old
* @return array
*/
protected static function formatAs($new, $old)
{
if (isset($old['as'])) {
$new['as'] = $old['as'].($new['as'] ?? '');
}
return $new;
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Arr;
class RouteParameterBinder
{
/**
* The route instance.
*
* @var \Illuminate\Routing\Route
*/
protected $route;
/**
* Create a new Route parameter binder instance.
*
* @param \Illuminate\Routing\Route $route
* @return void
*/
public function __construct($route)
{
$this->route = $route;
}
/**
* Get the parameters for the route.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function parameters($request)
{
// If the route has a regular expression for the host part of the URI, we will
// compile that and get the parameter matches for this domain. We will then
// merge them into this parameters array so that this array is completed.
$parameters = $this->bindPathParameters($request);
// If the route has a regular expression for the host part of the URI, we will
// compile that and get the parameter matches for this domain. We will then
// merge them into this parameters array so that this array is completed.
if (! is_null($this->route->compiled->getHostRegex())) {
$parameters = $this->bindHostParameters(
$request, $parameters
);
}
return $this->replaceDefaults($parameters);
}
/**
* Get the parameter matches for the path portion of the URI.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function bindPathParameters($request)
{
$path = '/'.ltrim($request->decodedPath(), '/');
preg_match($this->route->compiled->getRegex(), $path, $matches);
return $this->matchToKeys(array_slice($matches, 1));
}
/**
* Extract the parameter list from the host part of the request.
*
* @param \Illuminate\Http\Request $request
* @param array $parameters
* @return array
*/
protected function bindHostParameters($request, $parameters)
{
preg_match($this->route->compiled->getHostRegex(), $request->getHost(), $matches);
return array_merge($this->matchToKeys(array_slice($matches, 1)), $parameters);
}
/**
* Combine a set of parameter matches with the route's keys.
*
* @param array $matches
* @return array
*/
protected function matchToKeys(array $matches)
{
if (empty($parameterNames = $this->route->parameterNames())) {
return [];
}
$parameters = array_intersect_key($matches, array_flip($parameterNames));
return array_filter($parameters, function ($value) {
return is_string($value) && strlen($value) > 0;
});
}
/**
* Replace null parameters with their defaults.
*
* @param array $parameters
* @return array
*/
protected function replaceDefaults(array $parameters)
{
foreach ($parameters as $key => $value) {
$parameters[$key] = $value ?? Arr::get($this->route->defaults, $key);
}
foreach ($this->route->defaults as $key => $value) {
if (! isset($parameters[$key])) {
$parameters[$key] = $value;
}
}
return $parameters;
}
}
<?php
namespace Illuminate\Routing;
use Closure;
use BadMethodCallException;
use Illuminate\Support\Arr;
use InvalidArgumentException;
class RouteRegistrar
{
/**
* The router instance.
*
* @var \Illuminate\Routing\Router
*/
protected $router;
/**
* The attributes to pass on to the router.
*
* @var array
*/
protected $attributes = [];
/**
* The methods to dynamically pass through to the router.
*
* @var array
*/
protected $passthru = [
'get', 'post', 'put', 'patch', 'delete', 'options', 'any',
];
/**
* The attributes that can be set through this class.
*
* @var array
*/
protected $allowedAttributes = [
'as', 'domain', 'middleware', 'name', 'namespace', 'prefix',
];
/**
* The attributes that are aliased.
*
* @var array
*/
protected $aliases = [
'name' => 'as',
];
/**
* Create a new route registrar instance.
*
* @param \Illuminate\Routing\Router $router
* @return void
*/
public function __construct(Router $router)
{
$this->router = $router;
}
/**
* Set the value for a given attribute.
*
* @param string $key
* @param mixed $value
* @return $this
*
* @throws \InvalidArgumentException
*/
public function attribute($key, $value)
{
if (! in_array($key, $this->allowedAttributes)) {
throw new InvalidArgumentException("Attribute [{$key}] does not exist.");
}
$this->attributes[Arr::get($this->aliases, $key, $key)] = $value;
return $this;
}
/**
* Route a resource to a controller.
*
* @param string $name
* @param string $controller
* @param array $options
* @return \Illuminate\Routing\PendingResourceRegistration
*/
public function resource($name, $controller, array $options = [])
{
return $this->router->resource($name, $controller, $this->attributes + $options);
}
/**
* Create a route group with shared attributes.
*
* @param \Closure|string $callback
* @return void
*/
public function group($callback)
{
$this->router->group($this->attributes, $callback);
}
/**
* Register a new route with the given verbs.
*
* @param array|string $methods
* @param string $uri
* @param \Closure|array|string|null $action
* @return \Illuminate\Routing\Route
*/
public function match($methods, $uri, $action = null)
{
return $this->router->match($methods, $uri, $this->compileAction($action));
}
/**
* Register a new route with the router.
*
* @param string $method
* @param string $uri
* @param \Closure|array|string|null $action
* @return \Illuminate\Routing\Route
*/
protected function registerRoute($method, $uri, $action = null)
{
if (! is_array($action)) {
$action = array_merge($this->attributes, $action ? ['uses' => $action] : []);
}
return $this->router->{$method}($uri, $this->compileAction($action));
}
/**
* Compile the action into an array including the attributes.
*
* @param \Closure|array|string|null $action
* @return array
*/
protected function compileAction($action)
{
if (is_null($action)) {
return $this->attributes;
}
if (is_string($action) || $action instanceof Closure) {
$action = ['uses' => $action];
}
return array_merge($this->attributes, $action);
}
/**
* Dynamically handle calls into the route registrar.
*
* @param string $method
* @param array $parameters
* @return \Illuminate\Routing\Route|$this
*/
public function __call($method, $parameters)
{
if (in_array($method, $this->passthru)) {
return $this->registerRoute($method, ...$parameters);
}
if (in_array($method, $this->allowedAttributes)) {
if ($method == 'middleware') {
return $this->attribute($method, is_array($parameters[0]) ? $parameters[0] : $parameters);
}
return $this->attribute($method, $parameters[0]);
}
throw new BadMethodCallException("Method [{$method}] does not exist.");
}
}
<?php
namespace Illuminate\Routing;
use ReflectionMethod;
use ReflectionFunction;
use Illuminate\Support\Str;
class RouteSignatureParameters
{
/**
* Extract the route action's signature parameters.
*
* @param array $action
* @param string $subClass
* @return array
*/
public static function fromAction(array $action, $subClass = null)
{
$parameters = is_string($action['uses'])
? static::fromClassMethodString($action['uses'])
: (new ReflectionFunction($action['uses']))->getParameters();
return is_null($subClass) ? $parameters : array_filter($parameters, function ($p) use ($subClass) {
return $p->getClass() && $p->getClass()->isSubclassOf($subClass);
});
}
/**
* Get the parameters for the given class / method by string.
*
* @param string $uses
* @return array
*/
protected static function fromClassMethodString($uses)
{
list($class, $method) = Str::parseCallback($uses);
if (! method_exists($class, $method) && is_callable($class, $method)) {
return [];
}
return (new ReflectionMethod($class, $method))->getParameters();
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Routing\Exceptions\UrlGenerationException;
class RouteUrlGenerator
{
/**
* The URL generator instance.
*
* @var \Illuminate\Routing\UrlGenerator
*/
protected $url;
/**
* The request instance.
*
* @var \Illuminate\Http\Request
*/
protected $request;
/**
* The named parameter defaults.
*
* @var array
*/
public $defaultParameters = [];
/**
* Characters that should not be URL encoded.
*
* @var array
*/
public $dontEncode = [
'%2F' => '/',
'%40' => '@',
'%3A' => ':',
'%3B' => ';',
'%2C' => ',',
'%3D' => '=',
'%2B' => '+',
'%21' => '!',
'%2A' => '*',
'%7C' => '|',
'%3F' => '?',
'%26' => '&',
'%23' => '#',
'%25' => '%',
];
/**
* Create a new Route URL generator.
*
* @param \Illuminate\Routing\UrlGenerator $url
* @param \Illuminate\Http\Request $request
* @return void
*/
public function __construct($url, $request)
{
$this->url = $url;
$this->request = $request;
}
/**
* Generate a URL for the given route.
*
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @param bool $absolute
* @return string
*
* @throws \Illuminate\Routing\Exceptions\UrlGenerationException
*/
public function to($route, $parameters = [], $absolute = false)
{
$domain = $this->getRouteDomain($route, $parameters);
// First we will construct the entire URI including the root and query string. Once it
// has been constructed, we'll make sure we don't have any missing parameters or we
// will need to throw the exception to let the developers know one was not given.
$uri = $this->addQueryString($this->url->format(
$root = $this->replaceRootParameters($route, $domain, $parameters),
$this->replaceRouteParameters($route->uri(), $parameters)
), $parameters);
if (preg_match('/\{.*?\}/', $uri)) {
throw UrlGenerationException::forMissingParameters($route);
}
// Once we have ensured that there are no missing parameters in the URI we will encode
// the URI and prepare it for returning to the developer. If the URI is supposed to
// be absolute, we will return it as-is. Otherwise we will remove the URL's root.
$uri = strtr(rawurlencode($uri), $this->dontEncode);
if (! $absolute) {
return '/'.ltrim(str_replace($root, '', $uri), '/');
}
return $uri;
}
/**
* Get the formatted domain for a given route.
*
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @return string
*/
protected function getRouteDomain($route, &$parameters)
{
return $route->getDomain() ? $this->formatDomain($route, $parameters) : null;
}
/**
* Format the domain and port for the route and request.
*
* @param \Illuminate\Routing\Route $route
* @param array $parameters
* @return string
*/
protected function formatDomain($route, &$parameters)
{
return $this->addPortToDomain(
$this->getRouteScheme($route).$route->getDomain()
);
}
/**
* Get the scheme for the given route.
*
* @param \Illuminate\Routing\Route $route
* @return string
*/
protected function getRouteScheme($route)
{
if ($route->httpOnly()) {
return 'http://';
} elseif ($route->httpsOnly()) {
return 'https://';
}
return $this->url->formatScheme(null);
}
/**
* Add the port to the domain if necessary.
*
* @param string $domain
* @return string
*/
protected function addPortToDomain($domain)
{
$secure = $this->request->isSecure();
$port = (int) $this->request->getPort();
return ($secure && $port === 443) || (! $secure && $port === 80)
? $domain : $domain.':'.$port;
}
/**
* Replace the parameters on the root path.
*
* @param \Illuminate\Routing\Route $route
* @param string $domain
* @param array $parameters
* @return string
*/
protected function replaceRootParameters($route, $domain, &$parameters)
{
$scheme = $this->getRouteScheme($route);
return $this->replaceRouteParameters(
$this->url->formatRoot($scheme, $domain), $parameters
);
}
/**
* Replace all of the wildcard parameters for a route path.
*
* @param string $path
* @param array $parameters
* @return string
*/
protected function replaceRouteParameters($path, array &$parameters)
{
$path = $this->replaceNamedParameters($path, $parameters);
$path = preg_replace_callback('/\{.*?\}/', function ($match) use (&$parameters) {
return (empty($parameters) && ! Str::endsWith($match[0], '?}'))
? $match[0]
: array_shift($parameters);
}, $path);
return trim(preg_replace('/\{.*?\?\}/', '', $path), '/');
}
/**
* Replace all of the named parameters in the path.
*
* @param string $path
* @param array $parameters
* @return string
*/
protected function replaceNamedParameters($path, &$parameters)
{
return preg_replace_callback('/\{(.*?)\??\}/', function ($m) use (&$parameters) {
if (isset($parameters[$m[1]])) {
return Arr::pull($parameters, $m[1]);
} elseif (isset($this->defaultParameters[$m[1]])) {
return $this->defaultParameters[$m[1]];
}
return $m[0];
}, $path);
}
/**
* Add a query string to the URI.
*
* @param string $uri
* @param array $parameters
* @return mixed|string
*/
protected function addQueryString($uri, array $parameters)
{
// If the URI has a fragment we will move it to the end of this URI since it will
// need to come after any query string that may be added to the URL else it is
// not going to be available. We will remove it then append it back on here.
if (! is_null($fragment = parse_url($uri, PHP_URL_FRAGMENT))) {
$uri = preg_replace('/#.*/', '', $uri);
}
$uri .= $this->getRouteQueryString($parameters);
return is_null($fragment) ? $uri : $uri."#{$fragment}";
}
/**
* Get the query string for a given route.
*
* @param array $parameters
* @return string
*/
protected function getRouteQueryString(array $parameters)
{
// First we will get all of the string parameters that are remaining after we
// have replaced the route wildcards. We'll then build a query string from
// these string parameters then use it as a starting point for the rest.
if (count($parameters) == 0) {
return '';
}
$query = http_build_query(
$keyed = $this->getStringParameters($parameters)
);
// Lastly, if there are still parameters remaining, we will fetch the numeric
// parameters that are in the array and add them to the query string or we
// will make the initial query string if it wasn't started with strings.
if (count($keyed) < count($parameters)) {
$query .= '&'.implode(
'&', $this->getNumericParameters($parameters)
);
}
return '?'.trim($query, '&');
}
/**
* Get the string parameters from a given list.
*
* @param array $parameters
* @return array
*/
protected function getStringParameters(array $parameters)
{
return array_filter($parameters, 'is_string', ARRAY_FILTER_USE_KEY);
}
/**
* Get the numeric parameters from a given list.
*
* @param array $parameters
* @return array
*/
protected function getNumericParameters(array $parameters)
{
return array_filter($parameters, 'is_numeric', ARRAY_FILTER_USE_KEY);
}
/**
* Set the default named parameters used by the URL generator.
*
* @param array $defaults
* @return void
*/
public function defaults(array $defaults)
{
$this->defaultParameters = array_merge(
$this->defaultParameters, $defaults
);
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\ServiceProvider;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response as PsrResponse;
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Illuminate\Contracts\View\Factory as ViewFactoryContract;
use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract;
use Illuminate\Routing\Contracts\ControllerDispatcher as ControllerDispatcherContract;
class RoutingServiceProvider extends ServiceProvider
{
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->registerRouter();
$this->registerUrlGenerator();
$this->registerRedirector();
$this->registerPsrRequest();
$this->registerPsrResponse();
$this->registerResponseFactory();
$this->registerControllerDispatcher();
}
/**
* Register the router instance.
*
* @return void
*/
protected function registerRouter()
{
$this->app->singleton('router', function ($app) {
return new Router($app['events'], $app);
});
}
/**
* Register the URL generator service.
*
* @return void
*/
protected function registerUrlGenerator()
{
$this->app->singleton('url', function ($app) {
$routes = $app['router']->getRoutes();
// The URL generator needs the route collection that exists on the router.
// Keep in mind this is an object, so we're passing by references here
// and all the registered routes will be available to the generator.
$app->instance('routes', $routes);
$url = new UrlGenerator(
$routes, $app->rebinding(
'request', $this->requestRebinder()
)
);
$url->setSessionResolver(function () {
return $this->app['session'];
});
// If the route collection is "rebound", for example, when the routes stay
// cached for the application, we will need to rebind the routes on the
// URL generator instance so it has the latest version of the routes.
$app->rebinding('routes', function ($app, $routes) {
$app['url']->setRoutes($routes);
});
return $url;
});
}
/**
* Get the URL generator request rebinder.
*
* @return \Closure
*/
protected function requestRebinder()
{
return function ($app, $request) {
$app['url']->setRequest($request);
};
}
/**
* Register the Redirector service.
*
* @return void
*/
protected function registerRedirector()
{
$this->app->singleton('redirect', function ($app) {
$redirector = new Redirector($app['url']);
// If the session is set on the application instance, we'll inject it into
// the redirector instance. This allows the redirect responses to allow
// for the quite convenient "with" methods that flash to the session.
if (isset($app['session.store'])) {
$redirector->setSession($app['session.store']);
}
return $redirector;
});
}
/**
* Register a binding for the PSR-7 request implementation.
*
* @return void
*/
protected function registerPsrRequest()
{
$this->app->bind(ServerRequestInterface::class, function ($app) {
return (new DiactorosFactory)->createRequest($app->make('request'));
});
}
/**
* Register a binding for the PSR-7 response implementation.
*
* @return void
*/
protected function registerPsrResponse()
{
$this->app->bind(ResponseInterface::class, function ($app) {
return new PsrResponse;
});
}
/**
* Register the response factory implementation.
*
* @return void
*/
protected function registerResponseFactory()
{
$this->app->singleton(ResponseFactoryContract::class, function ($app) {
return new ResponseFactory($app[ViewFactoryContract::class], $app['redirect']);
});
}
/**
* Register the controller dispatcher.
*
* @return void
*/
protected function registerControllerDispatcher()
{
$this->app->singleton(ControllerDispatcherContract::class, function ($app) {
return new ControllerDispatcher($app);
});
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Support\Collection;
class SortedMiddleware extends Collection
{
/**
* Create a new Sorted Middleware container.
*
* @param array $priorityMap
* @param array|Collection $middlewares
* @return void
*/
public function __construct(array $priorityMap, $middlewares)
{
if ($middlewares instanceof Collection) {
$middlewares = $middlewares->all();
}
$this->items = $this->sortMiddleware($priorityMap, $middlewares);
}
/**
* Sort the middlewares by the given priority map.
*
* Each call to this method makes one discrete middleware movement if necessary.
*
* @param array $priorityMap
* @param array $middlewares
* @return array
*/
protected function sortMiddleware($priorityMap, $middlewares)
{
$lastIndex = 0;
foreach ($middlewares as $index => $middleware) {
if (! is_string($middleware)) {
continue;
}
$stripped = head(explode(':', $middleware));
if (in_array($stripped, $priorityMap)) {
$priorityIndex = array_search($stripped, $priorityMap);
// This middleware is in the priority map. If we have encountered another middleware
// that was also in the priority map and was at a lower priority than the current
// middleware, we will move this middleware to be above the previous encounter.
if (isset($lastPriorityIndex) && $priorityIndex < $lastPriorityIndex) {
return $this->sortMiddleware(
$priorityMap, array_values($this->moveMiddleware($middlewares, $index, $lastIndex))
);
}
// This middleware is in the priority map; but, this is the first middleware we have
// encountered from the map thus far. We'll save its current index plus its index
// from the priority map so we can compare against them on the next iterations.
$lastIndex = $index;
$lastPriorityIndex = $priorityIndex;
}
}
return array_values(array_unique($middlewares, SORT_REGULAR));
}
/**
* Splice a middleware into a new position and remove the old entry.
*
* @param array $middlewares
* @param int $from
* @param int $to
* @return array
*/
protected function moveMiddleware($middlewares, $from, $to)
{
array_splice($middlewares, $to, 0, $middlewares[$from]);
unset($middlewares[$from + 1]);
return $middlewares;
}
}
<?php
namespace Illuminate\Routing;
use Illuminate\Contracts\View\Factory as ViewFactory;
class ViewController extends Controller
{
/**
* The view factory implementation.
*
* @var \Illuminate\Contracts\View\Factory
*/
protected $view;
/**
* Create a new controller instance.
*
* @param \Illuminate\Contracts\View\Factory $view
* @return void
*/
public function __construct(ViewFactory $view)
{
$this->view = $view;
}
/**
* Invoke the controller method.
*
* @param array $args
* @return \Illuminate\Contracts\View\View
*/
public function __invoke(...$args)
{
list($view, $data) = array_slice($args, -2);
return $this->view->make($view, $data);
}
}
{
"name": "illuminate/routing",
"description": "The Illuminate Routing package.",
"license": "MIT",
"homepage": "https://laravel.com",
"support": {
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"require": {
"php": ">=7.0",
"illuminate/container": "5.5.*",
"illuminate/contracts": "5.5.*",
"illuminate/http": "5.5.*",
"illuminate/pipeline": "5.5.*",
"illuminate/session": "5.5.*",
"illuminate/support": "5.5.*",
"symfony/debug": "~3.3",
"symfony/http-foundation": "~3.3",
"symfony/http-kernel": "~3.3",
"symfony/routing": "~3.3"
},
"autoload": {
"psr-4": {
"Illuminate\\Routing\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "5.5-dev"
}
},
"suggest": {
"illuminate/console": "Required to use the make commands (5.5.*).",
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (~1.0)."
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}
The MIT License (MIT)
Copyright (c) 2013 Phil Sturgeon <me@philsturgeon.uk>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
{
"name": "league/fractal",
"description": "Handle the output of complex data structures ready for API output.",
"keywords": [
"league",
"api",
"json",
"rest"
],
"homepage": "http://fractal.thephpleague.com/",
"license": "MIT",
"authors": [
{
"name": "Phil Sturgeon",
"email": "me@philsturgeon.uk",
"homepage": "http://philsturgeon.uk/",
"role": "Developer"
}
],
"config": {
"sort-packages": true
},
"require": {
"php": ">=5.4"
},
"require-dev": {
"doctrine/orm": "^2.5",
"illuminate/contracts": "~5.0",
"mockery/mockery": "~0.9",
"pagerfanta/pagerfanta": "~1.0.0",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5",
"zendframework/zend-paginator": "~2.3"
},
"suggest": {
"illuminate/pagination": "The Illuminate Pagination component.",
"pagerfanta/pagerfanta": "Pagerfanta Paginator",
"zendframework/zend-paginator": "Zend Framework Paginator"
},
"autoload": {
"psr-4": {
"League\\Fractal\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"League\\Fractal\\Test\\": "test"
}
},
"extra": {
"branch-alias": {
"dev-master": "0.13-dev"
}
}
}
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal;
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Serializer\DataArraySerializer;
use League\Fractal\Serializer\SerializerAbstract;
/**
* Manager
*
* Not a wildly creative name, but the manager is what a Fractal user will interact
* with the most. The manager has various configurable options, and allows users
* to create the "root scope" easily.
*/
class Manager
{
/**
* Array of scope identifiers for resources to include.
*
* @var array
*/
protected $requestedIncludes = [];
/**
* Array of scope identifiers for resources to exclude.
*
* @var array
*/
protected $requestedExcludes = [];
/**
* Array of requested fieldsets.
*
* @var array
*/
protected $requestedFieldsets = [];
/**
* Array containing modifiers as keys and an array value of params.
*
* @var array
*/
protected $includeParams = [];
/**
* The character used to separate modifier parameters.
*
* @var string
*/
protected $paramDelimiter = '|';
/**
* Upper limit to how many levels of included data are allowed.
*
* @var int
*/
protected $recursionLimit = 10;
/**
* Serializer.
*
* @var SerializerAbstract
*/
protected $serializer;
/**
* Factory used to create new configured scopes.
*
* @var ScopeFactoryInterface
*/
private $scopeFactory;
public function __construct(ScopeFactoryInterface $scopeFactory = null)
{
$this->scopeFactory = $scopeFactory ?: new ScopeFactory();
}
/**
* Create Data.
*
* Main method to kick this all off. Make a resource then pass it over, and use toArray()
*
* @param ResourceInterface $resource
* @param string $scopeIdentifier
* @param Scope $parentScopeInstance
*
* @return Scope
*/
public function createData(ResourceInterface $resource, $scopeIdentifier = null, Scope $parentScopeInstance = null)
{
if ($parentScopeInstance !== null) {
return $this->scopeFactory->createChildScopeFor($this, $parentScopeInstance, $resource, $scopeIdentifier);
}
return $this->scopeFactory->createScopeFor($this, $resource, $scopeIdentifier);
}
/**
* Get Include Params.
*
* @param string $include
*
* @return \League\Fractal\ParamBag
*/
public function getIncludeParams($include)
{
$params = isset($this->includeParams[$include]) ? $this->includeParams[$include] : [];
return new ParamBag($params);
}
/**
* Get Requested Includes.
*
* @return array
*/
public function getRequestedIncludes()
{
return $this->requestedIncludes;
}
/**
* Get Requested Excludes.
*
* @return array
*/
public function getRequestedExcludes()
{
return $this->requestedExcludes;
}
/**
* Get Serializer.
*
* @return SerializerAbstract
*/
public function getSerializer()
{
if (! $this->serializer) {
$this->setSerializer(new DataArraySerializer());
}
return $this->serializer;
}
/**
* Parse Include String.
*
* @param array|string $includes Array or csv string of resources to include
*
* @return $this
*/
public function parseIncludes($includes)
{
// Wipe these before we go again
$this->requestedIncludes = $this->includeParams = [];
if (is_string($includes)) {
$includes = explode(',', $includes);
}
if (! is_array($includes)) {
throw new \InvalidArgumentException(
'The parseIncludes() method expects a string or an array. '.gettype($includes).' given'
);
}
foreach ($includes as $include) {
list($includeName, $allModifiersStr) = array_pad(explode(':', $include, 2), 2, null);
// Trim it down to a cool level of recursion
$includeName = $this->trimToAcceptableRecursionLevel($includeName);
if (in_array($includeName, $this->requestedIncludes)) {
continue;
}
$this->requestedIncludes[] = $includeName;
// No Params? Bored
if ($allModifiersStr === null) {
continue;
}
// Matches multiple instances of 'something(foo|bar|baz)' in the string
// I guess it ignores : so you could use anything, but probably don't do that
preg_match_all('/([\w]+)(\(([^\)]+)\))?/', $allModifiersStr, $allModifiersArr);
// [0] is full matched strings...
$modifierCount = count($allModifiersArr[0]);
$modifierArr = [];
for ($modifierIt = 0; $modifierIt < $modifierCount; $modifierIt++) {
// [1] is the modifier
$modifierName = $allModifiersArr[1][$modifierIt];
// and [3] is delimited params
$modifierParamStr = $allModifiersArr[3][$modifierIt];
// Make modifier array key with an array of params as the value
$modifierArr[$modifierName] = explode($this->paramDelimiter, $modifierParamStr);
}
$this->includeParams[$includeName] = $modifierArr;
}
// This should be optional and public someday, but without it includes would never show up
$this->autoIncludeParents();
return $this;
}
/**
* Parse field parameter.
*
* @param array $fieldsets Array of fields to include. It must be an array
* whose keys are resource types and values a string
* of the fields to return, separated by a comma
*
* @return $this
*/
public function parseFieldsets(array $fieldsets)
{
$this->requestedFieldsets = [];
foreach ($fieldsets as $type => $fields) {
//Remove empty and repeated fields
$this->requestedFieldsets[$type] = array_unique(array_filter(explode(',', $fields)));
}
return $this;
}
/**
* Get requested fieldsets.
*
* @return array
*/
public function getRequestedFieldsets()
{
return $this->requestedFieldsets;
}
/**
* Get fieldset params for the specified type.
*
* @param string $type
*
* @return \League\Fractal\ParamBag|null
*/
public function getFieldset($type)
{
return !isset($this->requestedFieldsets[$type]) ?
null :
new ParamBag($this->requestedFieldsets[$type]);
}
/**
* Parse Exclude String.
*
* @param array|string $excludes Array or csv string of resources to exclude
*
* @return $this
*/
public function parseExcludes($excludes)
{
$this->requestedExcludes = [];
if (is_string($excludes)) {
$excludes = explode(',', $excludes);
}
if (! is_array($excludes)) {
throw new \InvalidArgumentException(
'The parseExcludes() method expects a string or an array. '.gettype($excludes).' given'
);
}
foreach ($excludes as $excludeName) {
$excludeName = $this->trimToAcceptableRecursionLevel($excludeName);
if (in_array($excludeName, $this->requestedExcludes)) {
continue;
}
$this->requestedExcludes[] = $excludeName;
}
return $this;
}
/**
* Set Recursion Limit.
*
* @param int $recursionLimit
*
* @return $this
*/
public function setRecursionLimit($recursionLimit)
{
$this->recursionLimit = $recursionLimit;
return $this;
}
/**
* Set Serializer
*
* @param SerializerAbstract $serializer
*
* @return $this
*/
public function setSerializer(SerializerAbstract $serializer)
{
$this->serializer = $serializer;
return $this;
}
/**
* Auto-include Parents
*
* Look at the requested includes and automatically include the parents if they
* are not explicitly requested. E.g: [foo, bar.baz] becomes [foo, bar, bar.baz]
*
* @internal
*
* @return void
*/
protected function autoIncludeParents()
{
$parsed = [];
foreach ($this->requestedIncludes as $include) {
$nested = explode('.', $include);
$part = array_shift($nested);
$parsed[] = $part;
while (count($nested) > 0) {
$part .= '.'.array_shift($nested);
$parsed[] = $part;
}
}
$this->requestedIncludes = array_values(array_unique($parsed));
}
/**
* Trim to Acceptable Recursion Level
*
* Strip off any requested resources that are too many levels deep, to avoid DiCaprio being chased
* by trains or whatever the hell that movie was about.
*
* @internal
*
* @param string $includeName
*
* @return string
*/
protected function trimToAcceptableRecursionLevel($includeName)
{
return implode('.', array_slice(explode('.', $includeName), 0, $this->recursionLimit));
}
}
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
/**
* A generic cursor adapter.
*
* @author Isern Palaus <ipalaus@ipalaus.com>
* @author Michele Massari <michele@michelemassari.net>
*/
class Cursor implements CursorInterface
{
/**
* Current cursor value.
*
* @var mixed
*/
protected $current;
/**
* Previous cursor value.
*
* @var mixed
*/
protected $prev;
/**
* Next cursor value.
*
* @var mixed
*/
protected $next;
/**
* Items being held for the current cursor position.
*
* @var int
*/
protected $count;
/**
* Create a new Cursor instance.
*
* @param int $current
* @param null $prev
* @param mixed $next
* @param int $count
*
* @return void
*/
public function __construct($current = null, $prev = null, $next = null, $count = null)
{
$this->current = $current;
$this->prev = $prev;
$this->next = $next;
$this->count = $count;
}
/**
* Get the current cursor value.
*
* @return mixed
*/
public function getCurrent()
{
return $this->current;
}
/**
* Set the current cursor value.
*
* @param int $current
*
* @return Cursor
*/
public function setCurrent($current)
{
$this->current = $current;
return $this;
}
/**
* Get the prev cursor value.
*
* @return mixed
*/
public function getPrev()
{
return $this->prev;
}
/**
* Set the prev cursor value.
*
* @param int $prev
*
* @return Cursor
*/
public function setPrev($prev)
{
$this->prev = $prev;
return $this;
}
/**
* Get the next cursor value.
*
* @return mixed
*/
public function getNext()
{
return $this->next;
}
/**
* Set the next cursor value.
*
* @param int $next
*
* @return Cursor
*/
public function setNext($next)
{
$this->next = $next;
return $this;
}
/**
* Returns the total items in the current cursor.
*
* @return int
*/
public function getCount()
{
return $this->count;
}
/**
* Set the total items in the current cursor.
*
* @param int $count
*
* @return Cursor
*/
public function setCount($count)
{
$this->count = $count;
return $this;
}
}
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
/**
* A common interface for cursors to use.
*
* @author Isern Palaus <ipalaus@ipalaus.com>
*/
interface CursorInterface
{
/**
* Get the current cursor value.
*
* @return mixed
*/
public function getCurrent();
/**
* Get the prev cursor value.
*
* @return mixed
*/
public function getPrev();
/**
* Get the next cursor value.
*
* @return mixed
*/
public function getNext();
/**
* Returns the total items in the current cursor.
*
* @return int
*/
public function getCount();
}
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
use Doctrine\ORM\Tools\Pagination\Paginator;
/**
* A paginator adapter for doctrine pagination.
*
* @author Fraser Stockley <fraser.stockley@gmail.com>
*/
class DoctrinePaginatorAdapter implements PaginatorInterface
{
/**
* The paginator instance.
* @var Paginator
*/
private $paginator;
/**
* The route generator.
*
* @var callable
*/
private $routeGenerator;
/**
* Create a new DoctrinePaginatorAdapter.
* @param Paginator $paginator
* @param callable $routeGenerator
*
*/
public function __construct(Paginator $paginator, callable $routeGenerator)
{
$this->paginator = $paginator;
$this->routeGenerator = $routeGenerator;
}
/**
* Get the current page.
*
* @return int
*/
public function getCurrentPage()
{
return ($this->paginator->getQuery()->getFirstResult() / $this->paginator->getQuery()->getMaxResults()) + 1;
}
/**
* Get the last page.
*
* @return int
*/
public function getLastPage()
{
return (int) ceil($this->getTotal() / $this->paginator->getQuery()->getMaxResults());
}
/**
* Get the total.
*
* @return int
*/
public function getTotal()
{
return count($this->paginator);
}
/**
* Get the count.
*
* @return int
*/
public function getCount()
{
return $this->paginator->getIterator()->count();
}
/**
* Get the number per page.
*
* @return int
*/
public function getPerPage()
{
return $this->paginator->getQuery()->getMaxResults();
}
/**
* Get the url for the given page.
*
* @param int $page
*
* @return string
*/
public function getUrl($page)
{
return call_user_func($this->getRouteGenerator(), $page);
}
/**
* Get the the route generator.
*
* @return callable
*/
private function getRouteGenerator()
{
return $this->routeGenerator;
}
}
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
/**
* A paginator adapter for illuminate/pagination.
*
* @author Maxime Beaudoin <firalabs@gmail.com>
* @author Marc Addeo <marcaddeo@gmail.com>
*/
class IlluminatePaginatorAdapter implements PaginatorInterface
{
/**
* The paginator instance.
*
* @var \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
protected $paginator;
/**
* Create a new illuminate pagination adapter.
*
* @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $paginator
*
* @return void
*/
public function __construct(LengthAwarePaginator $paginator)
{
$this->paginator = $paginator;
}
/**
* Get the current page.
*
* @return int
*/
public function getCurrentPage()
{
return $this->paginator->currentPage();
}
/**
* Get the last page.
*
* @return int
*/
public function getLastPage()
{
return $this->paginator->lastPage();
}
/**
* Get the total.
*
* @return int
*/
public function getTotal()
{
return $this->paginator->total();
}
/**
* Get the count.
*
* @return int
*/
public function getCount()
{
return $this->paginator->count();
}
/**
* Get the number per page.
*
* @return int
*/
public function getPerPage()
{
return $this->paginator->perPage();
}
/**
* Get the url for the given page.
*
* @param int $page
*
* @return string
*/
public function getUrl($page)
{
return $this->paginator->url($page);
}
/**
* Get the paginator instance.
*
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
*/
public function getPaginator()
{
return $this->paginator;
}
}
<?php
/*
* This file is part of the League\Fractal package.
*
* (c) Phil Sturgeon <me@philsturgeon.uk>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Fractal\Pagination;
use Pagerfanta\Pagerfanta;
/**
* A paginator adapter for pagerfanta/pagerfanta.
*
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
*/
class PagerfantaPaginatorAdapter implements PaginatorInterface
{
/**
* The paginator instance.
*
* @var \Pagerfanta\Pagerfanta
*/
protected $paginator;
/**
* The route generator.
*
* @var callable
*/
protected $routeGenerator;
/**
* Create a new pagerfanta pagination adapter.
*
* @param \Pagerfanta\Pagerfanta $paginator
* @param callable $routeGenerator
*
* @return void
*/
public function __construct(Pagerfanta $paginator, $routeGenerator)
{
$this->paginator = $paginator;
$this->routeGenerator = $routeGenerator;
}
/**
* Get the current page.
*
* @return int
*/
public function getCurrentPage()
{
return $this->paginator->getCurrentPage();
}
/**
* Get the last page.
*
* @return int
*/
public function getLastPage()
{
return $this->paginator->getNbPages();
}
/**
* Get the total.
*
* @return int
*/
public function getTotal()
{
return count($this->paginator);
}
/**
* Get the count.
*
* @return int
*/
public function getCount()
{
return count($this->paginator->getCurrentPageResults());
}
/**
* Get the number per page.
*
* @return int
*/
public function getPerPage()
{
return $this->paginator->getMaxPerPage();
}
/**
* Get the url for the given page.
*
* @param int $page
*
* @return string
*/
public function getUrl($page)
{
return call_user_func($this->routeGenerator, $page);
}
/**
* Get the paginator instance.
*
* @return \Pagerfanta\Pagerfanta
*/
public function getPaginator()
{
return $this->paginator;
}
/**
* Get the the route generator.
*
* @return callable
*/
public function getRouteGenerator()
{
return $this->routeGenerator;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment