Upgrade framework
This commit is contained in:
284
vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php
vendored
Normal file
284
vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Str;
|
||||
use IteratorAggregate;
|
||||
use LogicException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper;
|
||||
use Symfony\Component\Routing\RouteCollection as SymfonyRouteCollection;
|
||||
use Traversable;
|
||||
|
||||
abstract class AbstractRouteCollection implements Countable, IteratorAggregate, RouteCollectionInterface
|
||||
{
|
||||
/**
|
||||
* Handle the matched route.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Routing\Route|null $route
|
||||
* @return \Illuminate\Routing\Route
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
protected function handleMatchedRoute(Request $request, $route)
|
||||
{
|
||||
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(sprintf(
|
||||
'The route %s could not be found.',
|
||||
$request->path()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
return array_values(array_filter(
|
||||
$methods,
|
||||
function ($method) use ($request) {
|
||||
return ! is_null($this->matchAgainstRoutes($this->get($method), $request, false));
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a route in the array matches the request.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route[] $routes
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param bool $includingMethod
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
protected function matchAgainstRoutes(array $routes, $request, $includingMethod = true)
|
||||
{
|
||||
[$fallbacks, $routes] = collect($routes)->partition(function ($route) {
|
||||
return $route->isFallback;
|
||||
});
|
||||
|
||||
return $routes->merge($fallbacks)->first(
|
||||
fn (Route $route) => $route->matches($request, $includingMethod)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a route (if necessary) that responds when other available methods are present.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string[] $methods
|
||||
* @return \Illuminate\Routing\Route
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
|
||||
*/
|
||||
protected function getRouteForMethods($request, array $methods)
|
||||
{
|
||||
if ($request->isMethod('OPTIONS')) {
|
||||
return (new Route('OPTIONS', $request->path(), function () use ($methods) {
|
||||
return new Response('', 200, ['Allow' => implode(',', $methods)]);
|
||||
}))->bind($request);
|
||||
}
|
||||
|
||||
$this->requestMethodNotAllowed($request, $methods, $request->method());
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a method not allowed HTTP exception.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param array $others
|
||||
* @param string $method
|
||||
* @return void
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
|
||||
*/
|
||||
protected function requestMethodNotAllowed($request, array $others, $method)
|
||||
{
|
||||
throw new MethodNotAllowedHttpException(
|
||||
$others,
|
||||
sprintf(
|
||||
'The %s method is not supported for route %s. Supported methods: %s.',
|
||||
$request->path(),
|
||||
$method,
|
||||
implode(', ', $others)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a method not allowed HTTP exception.
|
||||
*
|
||||
* @param array $others
|
||||
* @param string $method
|
||||
* @return void
|
||||
*
|
||||
* @deprecated use requestMethodNotAllowed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
|
||||
*/
|
||||
protected function methodNotAllowed(array $others, $method)
|
||||
{
|
||||
throw new MethodNotAllowedHttpException(
|
||||
$others,
|
||||
sprintf(
|
||||
'The %s method is not supported for this route. Supported methods: %s.',
|
||||
$method,
|
||||
implode(', ', $others)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the routes for caching.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function compile()
|
||||
{
|
||||
$compiled = $this->dumper()->getCompiledRoutes();
|
||||
|
||||
$attributes = [];
|
||||
|
||||
foreach ($this->getRoutes() as $route) {
|
||||
$attributes[$route->getName()] = [
|
||||
'methods' => $route->methods(),
|
||||
'uri' => $route->uri(),
|
||||
'action' => $route->getAction(),
|
||||
'fallback' => $route->isFallback,
|
||||
'defaults' => $route->defaults,
|
||||
'wheres' => $route->wheres,
|
||||
'bindingFields' => $route->bindingFields(),
|
||||
'lockSeconds' => $route->locksFor(),
|
||||
'waitSeconds' => $route->waitsFor(),
|
||||
'withTrashed' => $route->allowsTrashedBindings(),
|
||||
];
|
||||
}
|
||||
|
||||
return compact('compiled', 'attributes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CompiledUrlMatcherDumper instance for the route collection.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper
|
||||
*/
|
||||
public function dumper()
|
||||
{
|
||||
return new CompiledUrlMatcherDumper($this->toSymfonyRouteCollection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the collection to a Symfony RouteCollection instance.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
*/
|
||||
public function toSymfonyRouteCollection()
|
||||
{
|
||||
$symfonyRoutes = new SymfonyRouteCollection;
|
||||
|
||||
$routes = $this->getRoutes();
|
||||
|
||||
foreach ($routes as $route) {
|
||||
if (! $route->isFallback) {
|
||||
$symfonyRoutes = $this->addToSymfonyRoutesCollection($symfonyRoutes, $route);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($routes as $route) {
|
||||
if ($route->isFallback) {
|
||||
$symfonyRoutes = $this->addToSymfonyRoutesCollection($symfonyRoutes, $route);
|
||||
}
|
||||
}
|
||||
|
||||
return $symfonyRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a route to the SymfonyRouteCollection instance.
|
||||
*
|
||||
* @param \Symfony\Component\Routing\RouteCollection $symfonyRoutes
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
protected function addToSymfonyRoutesCollection(SymfonyRouteCollection $symfonyRoutes, Route $route)
|
||||
{
|
||||
$name = $route->getName();
|
||||
|
||||
if (
|
||||
! is_null($name)
|
||||
&& str_ends_with($name, '.')
|
||||
&& ! is_null($symfonyRoutes->get($name))
|
||||
) {
|
||||
$name = null;
|
||||
}
|
||||
|
||||
if (! $name) {
|
||||
$route->name($this->generateRouteName());
|
||||
|
||||
$this->add($route);
|
||||
} elseif (! is_null($symfonyRoutes->get($name))) {
|
||||
throw new LogicException("Unable to prepare route [{$route->uri}] for serialization. Another route has already been assigned name [{$name}].");
|
||||
}
|
||||
|
||||
$symfonyRoutes->add($route->getName(), $route->toSymfonyRoute());
|
||||
|
||||
return $symfonyRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a randomly generated route name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function generateRouteName()
|
||||
{
|
||||
return 'generated::'.Str::random();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an iterator for the items.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->getRoutes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->getRoutes());
|
||||
}
|
||||
}
|
||||
54
vendor/laravel/framework/src/Illuminate/Routing/CallableDispatcher.php
vendored
Normal file
54
vendor/laravel/framework/src/Illuminate/Routing/CallableDispatcher.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Routing\Contracts\CallableDispatcher as CallableDispatcherContract;
|
||||
use ReflectionFunction;
|
||||
|
||||
class CallableDispatcher implements CallableDispatcherContract
|
||||
{
|
||||
use RouteDependencyResolverTrait;
|
||||
|
||||
/**
|
||||
* The container instance.
|
||||
*
|
||||
* @var \Illuminate\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new callable dispatcher instance.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a request to a given callable.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param callable $callable
|
||||
* @return mixed
|
||||
*/
|
||||
public function dispatch(Route $route, $callable)
|
||||
{
|
||||
return $callable(...array_values($this->resolveParameters($route, $callable)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the parameters for the callable.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param callable $callable
|
||||
* @return array
|
||||
*/
|
||||
protected function resolveParameters(Route $route, $callable)
|
||||
{
|
||||
return $this->resolveMethodDependencies($route->parametersWithoutNulls(), new ReflectionFunction($callable));
|
||||
}
|
||||
}
|
||||
330
vendor/laravel/framework/src/Illuminate/Routing/CompiledRouteCollection.php
vendored
Normal file
330
vendor/laravel/framework/src/Illuminate/Routing/CompiledRouteCollection.php
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
|
||||
use Symfony\Component\Routing\RequestContext;
|
||||
|
||||
class CompiledRouteCollection extends AbstractRouteCollection
|
||||
{
|
||||
/**
|
||||
* The compiled routes collection.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $compiled = [];
|
||||
|
||||
/**
|
||||
* An array of the route attributes keyed by name.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $attributes = [];
|
||||
|
||||
/**
|
||||
* The dynamically added routes that were added after loading the cached, compiled routes.
|
||||
*
|
||||
* @var \Illuminate\Routing\RouteCollection|null
|
||||
*/
|
||||
protected $routes;
|
||||
|
||||
/**
|
||||
* The router instance used by the route.
|
||||
*
|
||||
* @var \Illuminate\Routing\Router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* The container instance used by the route.
|
||||
*
|
||||
* @var \Illuminate\Container\Container
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new CompiledRouteCollection instance.
|
||||
*
|
||||
* @param array $compiled
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $compiled, array $attributes)
|
||||
{
|
||||
$this->compiled = $compiled;
|
||||
$this->attributes = $attributes;
|
||||
$this->routes = new RouteCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Route instance to the collection.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
public function add(Route $route)
|
||||
{
|
||||
return $this->routes->add($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()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the action look-up table.
|
||||
*
|
||||
* This is done in case any actions are overwritten with new controllers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function refreshActionLookups()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first route matching a given request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Routing\Route
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function match(Request $request)
|
||||
{
|
||||
$matcher = new CompiledUrlMatcher(
|
||||
$this->compiled, (new RequestContext)->fromRequest(
|
||||
$trimmedRequest = $this->requestWithoutTrailingSlash($request)
|
||||
)
|
||||
);
|
||||
|
||||
$route = null;
|
||||
|
||||
try {
|
||||
if ($result = $matcher->matchRequest($trimmedRequest)) {
|
||||
$route = $this->getByName($result['_route']);
|
||||
}
|
||||
} catch (ResourceNotFoundException|MethodNotAllowedException $e) {
|
||||
try {
|
||||
return $this->routes->match($request);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
if ($route && $route->isFallback) {
|
||||
try {
|
||||
$dynamicRoute = $this->routes->match($request);
|
||||
|
||||
if (! $dynamicRoute->isFallback) {
|
||||
$route = $dynamicRoute;
|
||||
}
|
||||
} catch (NotFoundHttpException|MethodNotAllowedHttpException $e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
return $this->handleMatchedRoute($request, $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cloned instance of the given request without any trailing slash on the URI.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Request
|
||||
*/
|
||||
protected function requestWithoutTrailingSlash(Request $request)
|
||||
{
|
||||
$trimmedRequest = $request->duplicate();
|
||||
|
||||
$parts = explode('?', $request->server->get('REQUEST_URI'), 2);
|
||||
|
||||
$trimmedRequest->server->set(
|
||||
'REQUEST_URI', rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '')
|
||||
);
|
||||
|
||||
return $trimmedRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get routes from the collection by method.
|
||||
*
|
||||
* @param string|null $method
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function get($method = null)
|
||||
{
|
||||
return $this->getRoutesByMethod()[$method] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route collection contains a given named route.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNamedRoute($name)
|
||||
{
|
||||
return isset($this->attributes[$name]) || $this->routes->hasNamedRoute($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a route instance by its name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
public function getByName($name)
|
||||
{
|
||||
if (isset($this->attributes[$name])) {
|
||||
return $this->newRoute($this->attributes[$name]);
|
||||
}
|
||||
|
||||
return $this->routes->getByName($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a route instance by its controller action.
|
||||
*
|
||||
* @param string $action
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
public function getByAction($action)
|
||||
{
|
||||
$attributes = collect($this->attributes)->first(function (array $attributes) use ($action) {
|
||||
if (isset($attributes['action']['controller'])) {
|
||||
return trim($attributes['action']['controller'], '\\') === $action;
|
||||
}
|
||||
|
||||
return $attributes['action']['uses'] === $action;
|
||||
});
|
||||
|
||||
if ($attributes) {
|
||||
return $this->newRoute($attributes);
|
||||
}
|
||||
|
||||
return $this->routes->getByAction($action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the routes in the collection.
|
||||
*
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function getRoutes()
|
||||
{
|
||||
return collect($this->attributes)
|
||||
->map(function (array $attributes) {
|
||||
return $this->newRoute($attributes);
|
||||
})
|
||||
->merge($this->routes->getRoutes())
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the routes keyed by their HTTP verb / method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRoutesByMethod()
|
||||
{
|
||||
return collect($this->getRoutes())
|
||||
->groupBy(function (Route $route) {
|
||||
return $route->methods();
|
||||
})
|
||||
->map(function (Collection $routes) {
|
||||
return $routes->mapWithKeys(function (Route $route) {
|
||||
return [$route->getDomain().$route->uri => $route];
|
||||
})->all();
|
||||
})
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the routes keyed by their name.
|
||||
*
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function getRoutesByName()
|
||||
{
|
||||
return collect($this->getRoutes())
|
||||
->keyBy(function (Route $route) {
|
||||
return $route->getName();
|
||||
})
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve an array of attributes to a Route instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function newRoute(array $attributes)
|
||||
{
|
||||
if (empty($attributes['action']['prefix'] ?? '')) {
|
||||
$baseUri = $attributes['uri'];
|
||||
} else {
|
||||
$prefix = trim($attributes['action']['prefix'], '/');
|
||||
|
||||
$baseUri = trim(implode(
|
||||
'/', array_slice(
|
||||
explode('/', trim($attributes['uri'], '/')),
|
||||
count($prefix !== '' ? explode('/', $prefix) : [])
|
||||
)
|
||||
), '/');
|
||||
}
|
||||
|
||||
return $this->router->newRoute($attributes['methods'], $baseUri === '' ? '/' : $baseUri, $attributes['action'])
|
||||
->setFallback($attributes['fallback'])
|
||||
->setDefaults($attributes['defaults'])
|
||||
->setWheres($attributes['wheres'])
|
||||
->setBindingFields($attributes['bindingFields'])
|
||||
->block($attributes['lockSeconds'] ?? null, $attributes['waitSeconds'] ?? null)
|
||||
->withTrashed($attributes['withTrashed'] ?? false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the router instance on the route.
|
||||
*
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
* @return $this
|
||||
*/
|
||||
public function setRouter(Router $router)
|
||||
{
|
||||
$this->router = $router;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the container instance on the route.
|
||||
*
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @return $this
|
||||
*/
|
||||
public function setContainer(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,17 @@
|
||||
|
||||
namespace Illuminate\Routing\Console;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Console\Concerns\CreatesMatchingTest;
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
#[AsCommand(name: 'make:controller')]
|
||||
class ControllerMakeCommand extends GeneratorCommand
|
||||
{
|
||||
use CreatesMatchingTest;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
@@ -16,6 +20,17 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected $name = 'make:controller';
|
||||
|
||||
/**
|
||||
* The name of the console command.
|
||||
*
|
||||
* This name is used to identify the command during lazy loading.
|
||||
*
|
||||
* @var string|null
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected static $defaultName = 'make:controller';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
@@ -37,15 +52,46 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getStub()
|
||||
{
|
||||
if ($this->option('parent')) {
|
||||
return __DIR__.'/stubs/controller.nested.stub';
|
||||
$stub = null;
|
||||
|
||||
if ($type = $this->option('type')) {
|
||||
$stub = "/stubs/controller.{$type}.stub";
|
||||
} elseif ($this->option('parent')) {
|
||||
$stub = $this->option('singleton')
|
||||
? '/stubs/controller.nested.singleton.stub'
|
||||
: '/stubs/controller.nested.stub';
|
||||
} elseif ($this->option('model')) {
|
||||
return __DIR__.'/stubs/controller.model.stub';
|
||||
$stub = '/stubs/controller.model.stub';
|
||||
} elseif ($this->option('invokable')) {
|
||||
$stub = '/stubs/controller.invokable.stub';
|
||||
} elseif ($this->option('singleton')) {
|
||||
$stub = '/stubs/controller.singleton.stub';
|
||||
} elseif ($this->option('resource')) {
|
||||
return __DIR__.'/stubs/controller.stub';
|
||||
$stub = '/stubs/controller.stub';
|
||||
}
|
||||
|
||||
return __DIR__.'/stubs/controller.plain.stub';
|
||||
if ($this->option('api') && is_null($stub)) {
|
||||
$stub = '/stubs/controller.api.stub';
|
||||
} elseif ($this->option('api') && ! is_null($stub) && ! $this->option('invokable')) {
|
||||
$stub = str_replace('.stub', '.api.stub', $stub);
|
||||
}
|
||||
|
||||
$stub ??= '/stubs/controller.plain.stub';
|
||||
|
||||
return $this->resolveStubPath($stub);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fully-qualified path to the stub.
|
||||
*
|
||||
* @param string $stub
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveStubPath($stub)
|
||||
{
|
||||
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||||
? $customPath
|
||||
: __DIR__.$stub;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +108,7 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
/**
|
||||
* Build the class with the given name.
|
||||
*
|
||||
* Remove the base controller import if we are already in base namespace.
|
||||
* Remove the base controller import if we are already in the base namespace.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
@@ -81,6 +127,10 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
$replace = $this->buildModelReplacements($replace);
|
||||
}
|
||||
|
||||
if ($this->option('creatable')) {
|
||||
$replace['abort(404);'] = '//';
|
||||
}
|
||||
|
||||
$replace["use {$controllerNamespace}\Controller;\n"] = '';
|
||||
|
||||
return str_replace(
|
||||
@@ -97,16 +147,21 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
{
|
||||
$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]);
|
||||
}
|
||||
if (! class_exists($parentModelClass) &&
|
||||
$this->components->confirm("A {$parentModelClass} model does not exist. Do you want to generate it?", true)) {
|
||||
$this->call('make:model', ['name' => $parentModelClass]);
|
||||
}
|
||||
|
||||
return [
|
||||
'ParentDummyFullModelClass' => $parentModelClass,
|
||||
'{{ namespacedParentModel }}' => $parentModelClass,
|
||||
'{{namespacedParentModel}}' => $parentModelClass,
|
||||
'ParentDummyModelClass' => class_basename($parentModelClass),
|
||||
'{{ parentModel }}' => class_basename($parentModelClass),
|
||||
'{{parentModel}}' => class_basename($parentModelClass),
|
||||
'ParentDummyModelVariable' => lcfirst(class_basename($parentModelClass)),
|
||||
'{{ parentModelVariable }}' => lcfirst(class_basename($parentModelClass)),
|
||||
'{{parentModelVariable}}' => lcfirst(class_basename($parentModelClass)),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -120,16 +175,22 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
{
|
||||
$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]);
|
||||
}
|
||||
if (! class_exists($modelClass) && $this->components->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) {
|
||||
$this->call('make:model', ['name' => $modelClass]);
|
||||
}
|
||||
|
||||
$replace = $this->buildFormRequestReplacements($replace, $modelClass);
|
||||
|
||||
return array_merge($replace, [
|
||||
'DummyFullModelClass' => $modelClass,
|
||||
'{{ namespacedModel }}' => $modelClass,
|
||||
'{{namespacedModel}}' => $modelClass,
|
||||
'DummyModelClass' => class_basename($modelClass),
|
||||
'{{ model }}' => class_basename($modelClass),
|
||||
'{{model}}' => class_basename($modelClass),
|
||||
'DummyModelVariable' => lcfirst(class_basename($modelClass)),
|
||||
'{{ modelVariable }}' => lcfirst(class_basename($modelClass)),
|
||||
'{{modelVariable}}' => lcfirst(class_basename($modelClass)),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -138,6 +199,8 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
*
|
||||
* @param string $model
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function parseModel($model)
|
||||
{
|
||||
@@ -145,13 +208,73 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
throw new InvalidArgumentException('Model name contains invalid characters.');
|
||||
}
|
||||
|
||||
$model = trim(str_replace('/', '\\', $model), '\\');
|
||||
return $this->qualifyModel($model);
|
||||
}
|
||||
|
||||
if (! Str::startsWith($model, $rootNamespace = $this->laravel->getNamespace())) {
|
||||
$model = $rootNamespace.$model;
|
||||
/**
|
||||
* Build the model replacement values.
|
||||
*
|
||||
* @param array $replace
|
||||
* @param string $modelClass
|
||||
* @return array
|
||||
*/
|
||||
protected function buildFormRequestReplacements(array $replace, $modelClass)
|
||||
{
|
||||
[$namespace, $storeRequestClass, $updateRequestClass] = [
|
||||
'Illuminate\\Http', 'Request', 'Request',
|
||||
];
|
||||
|
||||
if ($this->option('requests')) {
|
||||
$namespace = 'App\\Http\\Requests';
|
||||
|
||||
[$storeRequestClass, $updateRequestClass] = $this->generateFormRequests(
|
||||
$modelClass, $storeRequestClass, $updateRequestClass
|
||||
);
|
||||
}
|
||||
|
||||
return $model;
|
||||
$namespacedRequests = $namespace.'\\'.$storeRequestClass.';';
|
||||
|
||||
if ($storeRequestClass !== $updateRequestClass) {
|
||||
$namespacedRequests .= PHP_EOL.'use '.$namespace.'\\'.$updateRequestClass.';';
|
||||
}
|
||||
|
||||
return array_merge($replace, [
|
||||
'{{ storeRequest }}' => $storeRequestClass,
|
||||
'{{storeRequest}}' => $storeRequestClass,
|
||||
'{{ updateRequest }}' => $updateRequestClass,
|
||||
'{{updateRequest}}' => $updateRequestClass,
|
||||
'{{ namespacedStoreRequest }}' => $namespace.'\\'.$storeRequestClass,
|
||||
'{{namespacedStoreRequest}}' => $namespace.'\\'.$storeRequestClass,
|
||||
'{{ namespacedUpdateRequest }}' => $namespace.'\\'.$updateRequestClass,
|
||||
'{{namespacedUpdateRequest}}' => $namespace.'\\'.$updateRequestClass,
|
||||
'{{ namespacedRequests }}' => $namespacedRequests,
|
||||
'{{namespacedRequests}}' => $namespacedRequests,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the form requests for the given model and classes.
|
||||
*
|
||||
* @param string $modelClass
|
||||
* @param string $storeRequestClass
|
||||
* @param string $updateRequestClass
|
||||
* @return array
|
||||
*/
|
||||
protected function generateFormRequests($modelClass, $storeRequestClass, $updateRequestClass)
|
||||
{
|
||||
$storeRequestClass = 'Store'.class_basename($modelClass).'Request';
|
||||
|
||||
$this->call('make:request', [
|
||||
'name' => $storeRequestClass,
|
||||
]);
|
||||
|
||||
$updateRequestClass = 'Update'.class_basename($modelClass).'Request';
|
||||
|
||||
$this->call('make:request', [
|
||||
'name' => $updateRequestClass,
|
||||
]);
|
||||
|
||||
return [$storeRequestClass, $updateRequestClass];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,11 +285,16 @@ class ControllerMakeCommand extends GeneratorCommand
|
||||
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.'],
|
||||
['api', null, InputOption::VALUE_NONE, 'Exclude the create and edit methods from the controller'],
|
||||
['type', null, InputOption::VALUE_REQUIRED, 'Manually specify the controller stub file to use'],
|
||||
['force', null, InputOption::VALUE_NONE, 'Create the class even if the controller already exists'],
|
||||
['invokable', 'i', InputOption::VALUE_NONE, 'Generate a single method, invokable controller class'],
|
||||
['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model'],
|
||||
['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class'],
|
||||
['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class'],
|
||||
['requests', 'R', InputOption::VALUE_NONE, 'Generate FormRequest classes for store and update'],
|
||||
['singleton', 's', InputOption::VALUE_NONE, 'Generate a singleton resource controller class'],
|
||||
['creatable', null, InputOption::VALUE_NONE, 'Indicate that a singleton resource should be creatable'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
|
||||
namespace Illuminate\Routing\Console;
|
||||
|
||||
use Illuminate\Console\Concerns\CreatesMatchingTest;
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
|
||||
#[AsCommand(name: 'make:middleware')]
|
||||
class MiddlewareMakeCommand extends GeneratorCommand
|
||||
{
|
||||
use CreatesMatchingTest;
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
@@ -13,6 +18,17 @@ class MiddlewareMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected $name = 'make:middleware';
|
||||
|
||||
/**
|
||||
* The name of the console command.
|
||||
*
|
||||
* This name is used to identify the command during lazy loading.
|
||||
*
|
||||
* @var string|null
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected static $defaultName = 'make:middleware';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
@@ -34,7 +50,20 @@ class MiddlewareMakeCommand extends GeneratorCommand
|
||||
*/
|
||||
protected function getStub()
|
||||
{
|
||||
return __DIR__.'/stubs/middleware.stub';
|
||||
return $this->resolveStubPath('/stubs/middleware.stub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the fully-qualified path to the stub.
|
||||
*
|
||||
* @param string $stub
|
||||
* @return string
|
||||
*/
|
||||
protected function resolveStubPath($stub)
|
||||
{
|
||||
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
|
||||
? $customPath
|
||||
: __DIR__.$stub;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
64
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.api.stub
vendored
Normal file
64
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.api.stub
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
20
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.invokable.stub
vendored
Normal file
20
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.invokable.stub
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Handle the incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
65
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.model.api.stub
vendored
Normal file
65
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.model.api.stub
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ namespacedModel }};
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use {{ namespacedRequests }}
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \{{ namespacedStoreRequest }} $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store({{ storeRequest }} $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show({{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \{{ namespacedUpdateRequest }} $request
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update({{ updateRequest }} $request, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy({{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
namespace {{ namespace }};
|
||||
|
||||
use DummyFullModelClass;
|
||||
use Illuminate\Http\Request;
|
||||
use DummyRootNamespaceHttp\Controllers\Controller;
|
||||
use {{ namespacedModel }};
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use {{ namespacedRequests }}
|
||||
|
||||
class DummyClass extends Controller
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
@@ -31,10 +31,10 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedStoreRequest }} $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store({{ storeRequest }} $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -42,10 +42,10 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(DummyModelClass $DummyModelVariable)
|
||||
public function show({{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -53,10 +53,10 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(DummyModelClass $DummyModelVariable)
|
||||
public function edit({{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -64,11 +64,11 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedUpdateRequest }} $request
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, DummyModelClass $DummyModelVariable)
|
||||
public function update({{ updateRequest }} $request, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -76,10 +76,10 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(DummyModelClass $DummyModelVariable)
|
||||
public function destroy({{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
71
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.nested.api.stub
vendored
Normal file
71
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.nested.api.stub
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ namespacedModel }};
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use {{ namespacedParentModel }};
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request, {{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show({{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, {{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy({{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ namespacedModel }};
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use {{ namespacedParentModel }};
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Store the newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request, {{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the resource.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, {{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the resource from storage.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
79
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.nested.singleton.stub
vendored
Normal file
79
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.nested.singleton.stub
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ namespacedModel }};
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use {{ namespacedParentModel }};
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the form for creating the new resource.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request, {{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the resource.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the resource.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, {{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the resource from storage.
|
||||
*
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
namespace {{ namespace }};
|
||||
|
||||
use DummyFullModelClass;
|
||||
use ParentDummyFullModelClass;
|
||||
use {{ namespacedModel }};
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use DummyRootNamespaceHttp\Controllers\Controller;
|
||||
use {{ namespacedParentModel }};
|
||||
|
||||
class DummyClass extends Controller
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(ParentDummyModelClass $ParentDummyModelVariable)
|
||||
public function index({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -23,10 +23,10 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create(ParentDummyModelClass $ParentDummyModelVariable)
|
||||
public function create({{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -35,10 +35,10 @@ class DummyClass extends Controller
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request, ParentDummyModelClass $ParentDummyModelVariable)
|
||||
public function store(Request $request, {{ parentModel }} ${{ parentModelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -46,11 +46,11 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
|
||||
public function show({{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -58,11 +58,11 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
|
||||
public function edit({{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -71,11 +71,11 @@ class DummyClass extends Controller
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
|
||||
public function update(Request $request, {{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -83,11 +83,11 @@ class DummyClass extends Controller
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \ParentDummyFullModelClass $ParentDummyModelVariable
|
||||
* @param \DummyFullModelClass $DummyModelVariable
|
||||
* @param \{{ namespacedParentModel }} ${{ parentModelVariable }}
|
||||
* @param \{{ namespacedModel }} ${{ modelVariable }}
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(ParentDummyModelClass $ParentDummyModelVariable, DummyModelClass $DummyModelVariable)
|
||||
public function destroy({{ parentModel }} ${{ parentModelVariable }}, {{ model }} ${{ modelVariable }})
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use DummyRootNamespaceHttp\Controllers\Controller;
|
||||
|
||||
class DummyClass extends Controller
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
51
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.singleton.api.stub
vendored
Normal file
51
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.singleton.api.stub
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Store the newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the resource from storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
71
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.singleton.stub
vendored
Normal file
71
vendor/laravel/framework/src/Illuminate/Routing/Console/stubs/controller.singleton.stub
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the form for creating the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the resource from storage.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
namespace {{ namespace }};
|
||||
|
||||
use {{ rootNamespace }}Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use DummyRootNamespaceHttp\Controllers\Controller;
|
||||
|
||||
class DummyClass extends Controller
|
||||
class {{ class }} extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
namespace {{ namespace }};
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DummyClass
|
||||
class {{ class }}
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
17
vendor/laravel/framework/src/Illuminate/Routing/Contracts/CallableDispatcher.php
vendored
Normal file
17
vendor/laravel/framework/src/Illuminate/Routing/Contracts/CallableDispatcher.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Contracts;
|
||||
|
||||
use Illuminate\Routing\Route;
|
||||
|
||||
interface CallableDispatcher
|
||||
{
|
||||
/**
|
||||
* Dispatch a request to a given callable.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param callable $callable
|
||||
* @return mixed
|
||||
*/
|
||||
public function dispatch(Route $route, $callable);
|
||||
}
|
||||
27
vendor/laravel/framework/src/Illuminate/Routing/Contracts/ControllerDispatcher.php
vendored
Normal file
27
vendor/laravel/framework/src/Illuminate/Routing/Contracts/ControllerDispatcher.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?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);
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
@@ -17,8 +16,8 @@ abstract class Controller
|
||||
/**
|
||||
* Register middleware on the controller.
|
||||
*
|
||||
* @param array|string|\Closure $middleware
|
||||
* @param array $options
|
||||
* @param \Closure|array|string $middleware
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\ControllerMiddlewareOptions
|
||||
*/
|
||||
public function middleware($middleware, array $options = [])
|
||||
@@ -47,38 +46,27 @@ abstract class Controller
|
||||
* Execute an action on the controller.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @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 array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function missingMethod($parameters = [])
|
||||
{
|
||||
throw new NotFoundHttpException('Controller method not found.');
|
||||
return $this->{$method}(...array_values($parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle calls to missing methods on the controller.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
throw new BadMethodCallException("Method [{$method}] does not exist.");
|
||||
throw new BadMethodCallException(sprintf(
|
||||
'Method %s::%s does not exist.', static::class, $method
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Routing\Contracts\ControllerDispatcher as ControllerDispatcherContract;
|
||||
|
||||
class ControllerDispatcher
|
||||
class ControllerDispatcher implements ControllerDispatcherContract
|
||||
{
|
||||
use RouteDependencyResolverTrait;
|
||||
|
||||
@@ -36,9 +37,7 @@ class ControllerDispatcher
|
||||
*/
|
||||
public function dispatch(Route $route, $controller, $method)
|
||||
{
|
||||
$parameters = $this->resolveClassMethodDependencies(
|
||||
$route->parametersWithoutNulls(), $controller, $method
|
||||
);
|
||||
$parameters = $this->resolveParameters($route, $controller, $method);
|
||||
|
||||
if (method_exists($controller, 'callAction')) {
|
||||
return $controller->callAction($method, $parameters);
|
||||
@@ -47,6 +46,21 @@ class ControllerDispatcher
|
||||
return $controller->{$method}(...array_values($parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the parameters for the controller.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param mixed $controller
|
||||
* @param string $method
|
||||
* @return array
|
||||
*/
|
||||
protected function resolveParameters(Route $route, $controller, $method)
|
||||
{
|
||||
return $this->resolveClassMethodDependencies(
|
||||
$route->parametersWithoutNulls(), $controller, $method
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the middleware for the controller instance.
|
||||
*
|
||||
@@ -54,7 +68,7 @@ class ControllerDispatcher
|
||||
* @param string $method
|
||||
* @return array
|
||||
*/
|
||||
public static function getMiddleware($controller, $method)
|
||||
public function getMiddleware($controller, $method)
|
||||
{
|
||||
if (! method_exists($controller, 'getMiddleware')) {
|
||||
return [];
|
||||
@@ -72,7 +86,7 @@ class ControllerDispatcher
|
||||
* @param array $options
|
||||
* @return bool
|
||||
*/
|
||||
protected static function methodExcludedByOptions($method, array $options)
|
||||
public 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']));
|
||||
|
||||
13
vendor/laravel/framework/src/Illuminate/Routing/Controllers/HasMiddleware.php
vendored
Normal file
13
vendor/laravel/framework/src/Illuminate/Routing/Controllers/HasMiddleware.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Controllers;
|
||||
|
||||
interface HasMiddleware
|
||||
{
|
||||
/**
|
||||
* Get the middleware that should be assigned to the controller.
|
||||
*
|
||||
* @return \Illuminate\Routing\Controllers\Middleware|array
|
||||
*/
|
||||
public static function middleware();
|
||||
}
|
||||
67
vendor/laravel/framework/src/Illuminate/Routing/Controllers/Middleware.php
vendored
Normal file
67
vendor/laravel/framework/src/Illuminate/Routing/Controllers/Middleware.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Controllers;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class Middleware
|
||||
{
|
||||
/**
|
||||
* The middleware that should be assigned.
|
||||
*
|
||||
* @var \Closure|string|array
|
||||
*/
|
||||
public $middleware;
|
||||
|
||||
/**
|
||||
* The controller methods the middleware should only apply to.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
public $only;
|
||||
|
||||
/**
|
||||
* The controller methods the middleware should not apply to.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
public $except;
|
||||
|
||||
/**
|
||||
* Create a new controller middleware definition.
|
||||
*
|
||||
* @param \Closure|string|array $middleware
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure|string|array $middleware)
|
||||
{
|
||||
$this->middleware = $middleware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the only controller methods the middleware should apply to.
|
||||
*
|
||||
* @param array|string $only
|
||||
* @return $this
|
||||
*/
|
||||
public function only(array|string $only)
|
||||
{
|
||||
$this->only = Arr::wrap($only);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the controller methods the middleware should not apply to.
|
||||
*
|
||||
* @param array|string $only
|
||||
* @return $this
|
||||
*/
|
||||
public function except(array|string $except)
|
||||
{
|
||||
$this->except = Arr::wrap($except);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
89
vendor/laravel/framework/src/Illuminate/Routing/CreatesRegularExpressionRouteConstraints.php
vendored
Normal file
89
vendor/laravel/framework/src/Illuminate/Routing/CreatesRegularExpressionRouteConstraints.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait CreatesRegularExpressionRouteConstraints
|
||||
{
|
||||
/**
|
||||
* Specify that the given route parameters must be alphabetic.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function whereAlpha($parameters)
|
||||
{
|
||||
return $this->assignExpressionToParameters($parameters, '[a-zA-Z]+');
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the given route parameters must be alphanumeric.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function whereAlphaNumeric($parameters)
|
||||
{
|
||||
return $this->assignExpressionToParameters($parameters, '[a-zA-Z0-9]+');
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the given route parameters must be numeric.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function whereNumber($parameters)
|
||||
{
|
||||
return $this->assignExpressionToParameters($parameters, '[0-9]+');
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the given route parameters must be ULIDs.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function whereUlid($parameters)
|
||||
{
|
||||
return $this->assignExpressionToParameters($parameters, '[0-7][0-9a-hjkmnp-tv-zA-HJKMNP-TV-Z]{25}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the given route parameters must be UUIDs.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function whereUuid($parameters)
|
||||
{
|
||||
return $this->assignExpressionToParameters($parameters, '[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}');
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the given route parameters must be one of the given values.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function whereIn($parameters, array $values)
|
||||
{
|
||||
return $this->assignExpressionToParameters($parameters, implode('|', $values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the given regular expression to the given parameters.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @param string $expression
|
||||
* @return $this
|
||||
*/
|
||||
protected function assignExpressionToParameters($parameters, $expression)
|
||||
{
|
||||
return $this->where(collect(Arr::wrap($parameters))
|
||||
->mapWithKeys(fn ($parameter) => [$parameter => $expression])
|
||||
->all());
|
||||
}
|
||||
}
|
||||
24
vendor/laravel/framework/src/Illuminate/Routing/Events/Routing.php
vendored
Normal file
24
vendor/laravel/framework/src/Illuminate/Routing/Events/Routing.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Events;
|
||||
|
||||
class Routing
|
||||
{
|
||||
/**
|
||||
* The request instance.
|
||||
*
|
||||
* @var \Illuminate\Http\Request
|
||||
*/
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
}
|
||||
20
vendor/laravel/framework/src/Illuminate/Routing/Exceptions/BackedEnumCaseNotFoundException.php
vendored
Normal file
20
vendor/laravel/framework/src/Illuminate/Routing/Exceptions/BackedEnumCaseNotFoundException.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Exceptions;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class BackedEnumCaseNotFoundException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $backedEnumClass
|
||||
* @param string $case
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($backedEnumClass, $case)
|
||||
{
|
||||
parent::__construct("Case [{$case}] not found on Backed Enum [{$backedEnumClass}].");
|
||||
}
|
||||
}
|
||||
18
vendor/laravel/framework/src/Illuminate/Routing/Exceptions/InvalidSignatureException.php
vendored
Normal file
18
vendor/laravel/framework/src/Illuminate/Routing/Exceptions/InvalidSignatureException.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Exceptions;
|
||||
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class InvalidSignatureException extends HttpException
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(403, 'Invalid signature.');
|
||||
}
|
||||
}
|
||||
50
vendor/laravel/framework/src/Illuminate/Routing/Exceptions/StreamedResponseException.php
vendored
Normal file
50
vendor/laravel/framework/src/Illuminate/Routing/Exceptions/StreamedResponseException.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Exceptions;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class StreamedResponseException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
* The actual exception thrown during the stream.
|
||||
*
|
||||
* @var \Throwable
|
||||
*/
|
||||
public $originalException;
|
||||
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param \Throwable $originalException
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Throwable $originalException)
|
||||
{
|
||||
$this->originalException = $originalException;
|
||||
|
||||
parent::__construct($originalException->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the exception.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return new Response('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual exception thrown during the stream.
|
||||
*
|
||||
* @return \Throwable
|
||||
*/
|
||||
public function getInnerException()
|
||||
{
|
||||
return $this->originalException;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace Illuminate\Routing\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UrlGenerationException extends Exception
|
||||
{
|
||||
@@ -10,10 +12,26 @@ class UrlGenerationException extends Exception
|
||||
* Create a new exception for missing route parameters.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param array $parameters
|
||||
* @return static
|
||||
*/
|
||||
public static function forMissingParameters($route)
|
||||
public static function forMissingParameters(Route $route, array $parameters = [])
|
||||
{
|
||||
return new static("Missing required parameters for [Route: {$route->getName()}] [URI: {$route->uri()}].");
|
||||
$parameterLabel = Str::plural('parameter', count($parameters));
|
||||
|
||||
$message = sprintf(
|
||||
'Missing required %s for [Route: %s] [URI: %s]',
|
||||
$parameterLabel,
|
||||
$route->getName(),
|
||||
$route->uri()
|
||||
);
|
||||
|
||||
if (count($parameters) > 0) {
|
||||
$message .= sprintf(' [Missing %s: %s]', $parameterLabel, implode(', ', $parameters));
|
||||
}
|
||||
|
||||
$message .= '.';
|
||||
|
||||
return new static($message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException;
|
||||
use Illuminate\Support\Reflector;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ImplicitRouteBinding
|
||||
{
|
||||
@@ -12,30 +17,87 @@ class ImplicitRouteBinding
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>
|
||||
* @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException
|
||||
*/
|
||||
public static function resolveForRoute($container, $route)
|
||||
{
|
||||
$parameters = $route->parameters();
|
||||
|
||||
foreach ($route->signatureParameters(Model::class) as $parameter) {
|
||||
if (! $parameterName = static::getParameterName($parameter->name, $parameters)) {
|
||||
$route = static::resolveBackedEnumsForRoute($route, $parameters);
|
||||
|
||||
foreach ($route->signatureParameters(['subClass' => UrlRoutable::class]) as $parameter) {
|
||||
if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameterValue = $parameters[$parameterName];
|
||||
|
||||
if ($parameterValue instanceof Model) {
|
||||
if ($parameterValue instanceof UrlRoutable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$model = $container->make($parameter->getClass()->name);
|
||||
$instance = $container->make(Reflector::getParameterClassName($parameter));
|
||||
|
||||
$route->setParameter($parameterName, $model->where(
|
||||
$model->getRouteKeyName(), $parameterValue
|
||||
)->firstOrFail());
|
||||
$parent = $route->parentOfParameter($parameterName);
|
||||
|
||||
$routeBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance))
|
||||
? 'resolveSoftDeletableRouteBinding'
|
||||
: 'resolveRouteBinding';
|
||||
|
||||
if ($parent instanceof UrlRoutable &&
|
||||
! $route->preventsScopedBindings() &&
|
||||
($route->enforcesScopedBindings() || array_key_exists($parameterName, $route->bindingFields()))) {
|
||||
$childRouteBindingMethod = $route->allowsTrashedBindings() && in_array(SoftDeletes::class, class_uses_recursive($instance))
|
||||
? 'resolveSoftDeletableChildRouteBinding'
|
||||
: 'resolveChildRouteBinding';
|
||||
|
||||
if (! $model = $parent->{$childRouteBindingMethod}(
|
||||
$parameterName, $parameterValue, $route->bindingFieldFor($parameterName)
|
||||
)) {
|
||||
throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
|
||||
}
|
||||
} elseif (! $model = $instance->{$routeBindingMethod}($parameterValue, $route->bindingFieldFor($parameterName))) {
|
||||
throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]);
|
||||
}
|
||||
|
||||
$route->setParameter($parameterName, $model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the Backed Enums route bindings for the route.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param array $parameters
|
||||
* @return \Illuminate\Routing\Route
|
||||
*
|
||||
* @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException
|
||||
*/
|
||||
protected static function resolveBackedEnumsForRoute($route, $parameters)
|
||||
{
|
||||
foreach ($route->signatureParameters(['backedEnum' => true]) as $parameter) {
|
||||
if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameterValue = $parameters[$parameterName];
|
||||
|
||||
$backedEnumClass = (string) $parameter->getType();
|
||||
|
||||
$backedEnum = $backedEnumClass::tryFrom((string) $parameterValue);
|
||||
|
||||
if (is_null($backedEnum)) {
|
||||
throw new BackedEnumCaseNotFoundException($backedEnumClass, $parameterValue);
|
||||
}
|
||||
|
||||
$route->setParameter($parameterName, $backedEnum);
|
||||
}
|
||||
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the parameter name if it exists in the given parameters.
|
||||
*
|
||||
@@ -49,9 +111,7 @@ class ImplicitRouteBinding
|
||||
return $name;
|
||||
}
|
||||
|
||||
$snakedName = snake_case($name);
|
||||
|
||||
if (array_key_exists($snakedName, $parameters)) {
|
||||
if (array_key_exists($snakedName = Str::snake($name), $parameters)) {
|
||||
return $snakedName;
|
||||
}
|
||||
}
|
||||
|
||||
21
vendor/laravel/framework/src/Illuminate/Routing/LICENSE.md
vendored
Normal file
21
vendor/laravel/framework/src/Illuminate/Routing/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Taylor Otwell
|
||||
|
||||
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.
|
||||
@@ -16,10 +16,12 @@ class HostValidator implements ValidatorInterface
|
||||
*/
|
||||
public function matches(Route $route, Request $request)
|
||||
{
|
||||
if (is_null($route->getCompiled()->getHostRegex())) {
|
||||
$hostRegex = $route->getCompiled()->getHostRegex();
|
||||
|
||||
if (is_null($hostRegex)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return preg_match($route->getCompiled()->getHostRegex(), $request->getHost());
|
||||
return preg_match($hostRegex, $request->getHost());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class UriValidator implements ValidatorInterface
|
||||
*/
|
||||
public function matches(Route $route, Request $request)
|
||||
{
|
||||
$path = $request->path() == '/' ? '/' : '/'.$request->path();
|
||||
$path = rtrim($request->getPathInfo(), '/') ?: '/';
|
||||
|
||||
return preg_match($route->getCompiled()->getRegex(), rawurldecode($path));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Illuminate\Routing\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Routing\Registrar;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
class SubstituteBindings
|
||||
{
|
||||
@@ -34,9 +35,17 @@ class SubstituteBindings
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$this->router->substituteBindings($route = $request->route());
|
||||
try {
|
||||
$this->router->substituteBindings($route = $request->route());
|
||||
|
||||
$this->router->substituteImplicitBindings($route);
|
||||
$this->router->substituteImplicitBindings($route);
|
||||
} catch (ModelNotFoundException $exception) {
|
||||
if ($route->getMissing()) {
|
||||
return $route->getMissing()($request, $exception);
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
@@ -3,12 +3,19 @@
|
||||
namespace Illuminate\Routing\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Cache\RateLimiter;
|
||||
use Illuminate\Cache\RateLimiting\Unlimited;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use Illuminate\Http\Exceptions\ThrottleRequestsException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ThrottleRequests
|
||||
{
|
||||
use InteractsWithTime;
|
||||
|
||||
/**
|
||||
* The rate limiter instance.
|
||||
*
|
||||
@@ -32,26 +39,121 @@ class ThrottleRequests
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param int $maxAttempts
|
||||
* @param int|string $maxAttempts
|
||||
* @param float|int $decayMinutes
|
||||
* @return mixed
|
||||
* @param string $prefix
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
|
||||
*/
|
||||
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
|
||||
public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1, $prefix = '')
|
||||
{
|
||||
$key = $this->resolveRequestSignature($request);
|
||||
|
||||
if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
|
||||
return $this->buildResponse($key, $maxAttempts);
|
||||
if (is_string($maxAttempts)
|
||||
&& func_num_args() === 3
|
||||
&& ! is_null($limiter = $this->limiter->limiter($maxAttempts))) {
|
||||
return $this->handleRequestUsingNamedLimiter($request, $next, $maxAttempts, $limiter);
|
||||
}
|
||||
|
||||
$this->limiter->hit($key, $decayMinutes);
|
||||
return $this->handleRequest(
|
||||
$request,
|
||||
$next,
|
||||
[
|
||||
(object) [
|
||||
'key' => $prefix.$this->resolveRequestSignature($request),
|
||||
'maxAttempts' => $this->resolveMaxAttempts($request, $maxAttempts),
|
||||
'decayMinutes' => $decayMinutes,
|
||||
'responseCallback' => null,
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $limiterName
|
||||
* @param \Closure $limiter
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
|
||||
*/
|
||||
protected function handleRequestUsingNamedLimiter($request, Closure $next, $limiterName, Closure $limiter)
|
||||
{
|
||||
$limiterResponse = $limiter($request);
|
||||
|
||||
if ($limiterResponse instanceof Response) {
|
||||
return $limiterResponse;
|
||||
} elseif ($limiterResponse instanceof Unlimited) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return $this->handleRequest(
|
||||
$request,
|
||||
$next,
|
||||
collect(Arr::wrap($limiterResponse))->map(function ($limit) use ($limiterName) {
|
||||
return (object) [
|
||||
'key' => md5($limiterName.$limit->key),
|
||||
'maxAttempts' => $limit->maxAttempts,
|
||||
'decayMinutes' => $limit->decayMinutes,
|
||||
'responseCallback' => $limit->responseCallback,
|
||||
];
|
||||
})->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param array $limits
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
|
||||
*/
|
||||
protected function handleRequest($request, Closure $next, array $limits)
|
||||
{
|
||||
foreach ($limits as $limit) {
|
||||
if ($this->limiter->tooManyAttempts($limit->key, $limit->maxAttempts)) {
|
||||
throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback);
|
||||
}
|
||||
|
||||
$this->limiter->hit($limit->key, $limit->decayMinutes * 60);
|
||||
}
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
return $this->addHeaders(
|
||||
$response, $maxAttempts,
|
||||
$this->calculateRemainingAttempts($key, $maxAttempts)
|
||||
);
|
||||
foreach ($limits as $limit) {
|
||||
$response = $this->addHeaders(
|
||||
$response,
|
||||
$limit->maxAttempts,
|
||||
$this->calculateRemainingAttempts($limit->key, $limit->maxAttempts)
|
||||
);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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];
|
||||
}
|
||||
|
||||
if (! is_numeric($maxAttempts) && $request->user()) {
|
||||
$maxAttempts = $request->user()->{$maxAttempts};
|
||||
}
|
||||
|
||||
return (int) $maxAttempts;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,30 +161,53 @@ class ThrottleRequests
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return string
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function resolveRequestSignature($request)
|
||||
{
|
||||
return $request->fingerprint();
|
||||
if ($user = $request->user()) {
|
||||
return sha1($user->getAuthIdentifier());
|
||||
} elseif ($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' response.
|
||||
* Create a 'too many attempts' exception.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string $key
|
||||
* @param int $maxAttempts
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @param callable|null $responseCallback
|
||||
* @return \Illuminate\Http\Exceptions\ThrottleRequestsException
|
||||
*/
|
||||
protected function buildResponse($key, $maxAttempts)
|
||||
protected function buildException($request, $key, $maxAttempts, $responseCallback = null)
|
||||
{
|
||||
$response = new Response('Too Many Attempts.', 429);
|
||||
$retryAfter = $this->getTimeUntilNextRetry($key);
|
||||
|
||||
$retryAfter = $this->limiter->availableIn($key);
|
||||
|
||||
return $this->addHeaders(
|
||||
$response, $maxAttempts,
|
||||
$headers = $this->getHeaders(
|
||||
$maxAttempts,
|
||||
$this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
|
||||
$retryAfter
|
||||
);
|
||||
|
||||
return is_callable($responseCallback)
|
||||
? new HttpResponseException($responseCallback($request, $headers))
|
||||
: new ThrottleRequestsException('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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,6 +221,33 @@ class ThrottleRequests
|
||||
*/
|
||||
protected function addHeaders(Response $response, $maxAttempts, $remainingAttempts, $retryAfter = null)
|
||||
{
|
||||
$response->headers->add(
|
||||
$this->getHeaders($maxAttempts, $remainingAttempts, $retryAfter, $response)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the limit headers information.
|
||||
*
|
||||
* @param int $maxAttempts
|
||||
* @param int $remainingAttempts
|
||||
* @param int|null $retryAfter
|
||||
* @param \Symfony\Component\HttpFoundation\Response|null $response
|
||||
* @return array
|
||||
*/
|
||||
protected function getHeaders($maxAttempts,
|
||||
$remainingAttempts,
|
||||
$retryAfter = null,
|
||||
?Response $response = null)
|
||||
{
|
||||
if ($response &&
|
||||
! is_null($response->headers->get('X-RateLimit-Remaining')) &&
|
||||
(int) $response->headers->get('X-RateLimit-Remaining') <= (int) $remainingAttempts) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'X-RateLimit-Limit' => $maxAttempts,
|
||||
'X-RateLimit-Remaining' => $remainingAttempts,
|
||||
@@ -103,12 +255,10 @@ class ThrottleRequests
|
||||
|
||||
if (! is_null($retryAfter)) {
|
||||
$headers['Retry-After'] = $retryAfter;
|
||||
$headers['X-RateLimit-Reset'] = Carbon::now()->getTimestamp() + $retryAfter;
|
||||
$headers['X-RateLimit-Reset'] = $this->availableAt($retryAfter);
|
||||
}
|
||||
|
||||
$response->headers->add($headers);
|
||||
|
||||
return $response;
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,10 +271,6 @@ class ThrottleRequests
|
||||
*/
|
||||
protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null)
|
||||
{
|
||||
if (is_null($retryAfter)) {
|
||||
return $this->limiter->retriesLeft($key, $maxAttempts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return is_null($retryAfter) ? $this->limiter->retriesLeft($key, $maxAttempts) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
122
vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequestsWithRedis.php
vendored
Normal file
122
vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequestsWithRedis.php
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Cache\RateLimiter;
|
||||
use Illuminate\Contracts\Redis\Factory as Redis;
|
||||
use Illuminate\Redis\Limiters\DurationLimiter;
|
||||
|
||||
class ThrottleRequestsWithRedis extends ThrottleRequests
|
||||
{
|
||||
/**
|
||||
* The Redis factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Redis\Factory
|
||||
*/
|
||||
protected $redis;
|
||||
|
||||
/**
|
||||
* The timestamp of the end of the current duration by key.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $decaysAt = [];
|
||||
|
||||
/**
|
||||
* The number of remaining slots by key.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $remaining = [];
|
||||
|
||||
/**
|
||||
* Create a new request throttler.
|
||||
*
|
||||
* @param \Illuminate\Cache\RateLimiter $limiter
|
||||
* @param \Illuminate\Contracts\Redis\Factory $redis
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(RateLimiter $limiter, Redis $redis)
|
||||
{
|
||||
parent::__construct($limiter);
|
||||
|
||||
$this->redis = $redis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param array $limits
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Illuminate\Http\Exceptions\ThrottleRequestsException
|
||||
*/
|
||||
protected function handleRequest($request, Closure $next, array $limits)
|
||||
{
|
||||
foreach ($limits as $limit) {
|
||||
if ($this->tooManyAttempts($limit->key, $limit->maxAttempts, $limit->decayMinutes)) {
|
||||
throw $this->buildException($request, $limit->key, $limit->maxAttempts, $limit->responseCallback);
|
||||
}
|
||||
}
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
foreach ($limits as $limit) {
|
||||
$response = $this->addHeaders(
|
||||
$response,
|
||||
$limit->maxAttempts,
|
||||
$this->calculateRemainingAttempts($limit->key, $limit->maxAttempts)
|
||||
);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ($key, $limiter) {
|
||||
[$this->decaysAt[$key], $this->remaining[$key]] = [
|
||||
$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)
|
||||
{
|
||||
return is_null($retryAfter) ? $this->remaining[$key] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of seconds until the lock is released.
|
||||
*
|
||||
* @param string $key
|
||||
* @return int
|
||||
*/
|
||||
protected function getTimeUntilNextRetry($key)
|
||||
{
|
||||
return $this->decaysAt[$key] - $this->currentTime();
|
||||
}
|
||||
}
|
||||
39
vendor/laravel/framework/src/Illuminate/Routing/Middleware/ValidateSignature.php
vendored
Normal file
39
vendor/laravel/framework/src/Illuminate/Routing/Middleware/ValidateSignature.php
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Routing\Exceptions\InvalidSignatureException;
|
||||
|
||||
class ValidateSignature
|
||||
{
|
||||
/**
|
||||
* The names of the parameters that should be ignored.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $ignore = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $relative
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Illuminate\Routing\Exceptions\InvalidSignatureException
|
||||
*/
|
||||
public function handle($request, Closure $next, $relative = null)
|
||||
{
|
||||
$ignore = property_exists($this, 'except') ? $this->except : $this->ignore;
|
||||
|
||||
if ($request->hasValidSignatureWhileIgnoring($ignore, $relative !== 'relative')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
throw new InvalidSignatureException;
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,10 @@ class MiddlewareNameResolver
|
||||
/**
|
||||
* Resolve the middleware name to a class name(s) preserving passed parameters.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Closure|string $name
|
||||
* @param array $map
|
||||
* @param array $middlewareGroups
|
||||
* @return string|array
|
||||
* @return \Closure|string|array
|
||||
*/
|
||||
public static function resolve($name, $map, $middlewareGroups)
|
||||
{
|
||||
@@ -21,26 +21,25 @@ class MiddlewareNameResolver
|
||||
// convenient on occasions when the developers are experimenting with them.
|
||||
if ($name instanceof Closure) {
|
||||
return $name;
|
||||
} elseif (isset($map[$name]) && $map[$name] instanceof Closure) {
|
||||
}
|
||||
|
||||
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.
|
||||
} elseif (isset($middlewareGroups[$name])) {
|
||||
return static::parseMiddlewareGroup(
|
||||
$name, $map, $middlewareGroups
|
||||
);
|
||||
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.
|
||||
} else {
|
||||
list($name, $parameters) = array_pad(explode(':', $name, 2), 2, null);
|
||||
[$name, $parameters] = array_pad(explode(':', $name, 2), 2, null);
|
||||
|
||||
return (isset($map[$name]) ? $map[$name] : $name).
|
||||
(! is_null($parameters) ? ':'.$parameters : '');
|
||||
}
|
||||
return ($map[$name] ?? $name).(! is_null($parameters) ? ':'.$parameters : '');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +66,7 @@ class MiddlewareNameResolver
|
||||
continue;
|
||||
}
|
||||
|
||||
list($middleware, $parameters) = array_pad(
|
||||
[$middleware, $parameters] = array_pad(
|
||||
explode(':', $middleware, 2), 2, null
|
||||
);
|
||||
|
||||
|
||||
268
vendor/laravel/framework/src/Illuminate/Routing/PendingResourceRegistration.php
vendored
Normal file
268
vendor/laravel/framework/src/Illuminate/Routing/PendingResourceRegistration.php
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
||||
class PendingResourceRegistration
|
||||
{
|
||||
use CreatesRegularExpressionRouteConstraints, Macroable;
|
||||
|
||||
/**
|
||||
* 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 = [];
|
||||
|
||||
/**
|
||||
* The resource's registration status.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $registered = false;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add middleware to the resource routes.
|
||||
*
|
||||
* @param mixed $middleware
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function middleware($middleware)
|
||||
{
|
||||
$middleware = Arr::wrap($middleware);
|
||||
|
||||
foreach ($middleware as $key => $value) {
|
||||
$middleware[$key] = (string) $value;
|
||||
}
|
||||
|
||||
$this->options['middleware'] = $middleware;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify middleware that should be removed from the resource routes.
|
||||
*
|
||||
* @param array|string $middleware
|
||||
* @return $this|array
|
||||
*/
|
||||
public function withoutMiddleware($middleware)
|
||||
{
|
||||
$this->options['excluded_middleware'] = array_merge(
|
||||
(array) ($this->options['excluded_middleware'] ?? []), Arr::wrap($middleware)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "where" constraints to the resource routes.
|
||||
*
|
||||
* @param mixed $wheres
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function where($wheres)
|
||||
{
|
||||
$this->options['wheres'] = $wheres;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the resource routes should have "shallow" nesting.
|
||||
*
|
||||
* @param bool $shallow
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function shallow($shallow = true)
|
||||
{
|
||||
$this->options['shallow'] = $shallow;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the callable that should be invoked on a missing model exception.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function missing($callback)
|
||||
{
|
||||
$this->options['missing'] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the resource routes should be scoped using the given binding fields.
|
||||
*
|
||||
* @param array $fields
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function scoped(array $fields = [])
|
||||
{
|
||||
$this->options['bindingFields'] = $fields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define which routes should allow "trashed" models to be retrieved when resolving implicit model bindings.
|
||||
*
|
||||
* @param array $methods
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function withTrashed(array $methods = [])
|
||||
{
|
||||
$this->options['trashed'] = $methods;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the resource route.
|
||||
*
|
||||
* @return \Illuminate\Routing\RouteCollection
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registered = true;
|
||||
|
||||
return $this->registrar->register(
|
||||
$this->name, $this->controller, $this->options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the object's destruction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (! $this->registered) {
|
||||
$this->register();
|
||||
}
|
||||
}
|
||||
}
|
||||
229
vendor/laravel/framework/src/Illuminate/Routing/PendingSingletonResourceRegistration.php
vendored
Normal file
229
vendor/laravel/framework/src/Illuminate/Routing/PendingSingletonResourceRegistration.php
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
||||
class PendingSingletonResourceRegistration
|
||||
{
|
||||
use CreatesRegularExpressionRouteConstraints, Macroable;
|
||||
|
||||
/**
|
||||
* 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 = [];
|
||||
|
||||
/**
|
||||
* The resource's registration status.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $registered = false;
|
||||
|
||||
/**
|
||||
* Create a new pending singleton 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\PendingSingletonResourceRegistration
|
||||
*/
|
||||
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\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function except($methods)
|
||||
{
|
||||
$this->options['except'] = is_array($methods) ? $methods : func_get_args();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the resource should have creation and storage routes.
|
||||
*
|
||||
* @param bool $creatable
|
||||
* @return $this
|
||||
*/
|
||||
public function creatable($creatable = true)
|
||||
{
|
||||
$this->options['creatable'] = $creatable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the route names for controller actions.
|
||||
*
|
||||
* @param array|string $names
|
||||
* @return \Illuminate\Routing\PendingSingletonResourceRegistration
|
||||
*/
|
||||
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\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function name($method, $name)
|
||||
{
|
||||
$this->options['names'][$method] = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the route parameter names.
|
||||
*
|
||||
* @param array|string $parameters
|
||||
* @return \Illuminate\Routing\PendingSingletonResourceRegistration
|
||||
*/
|
||||
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\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function parameter($previous, $new)
|
||||
{
|
||||
$this->options['parameters'][$previous] = $new;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add middleware to the resource routes.
|
||||
*
|
||||
* @param mixed $middleware
|
||||
* @return \Illuminate\Routing\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function middleware($middleware)
|
||||
{
|
||||
$middleware = Arr::wrap($middleware);
|
||||
|
||||
foreach ($middleware as $key => $value) {
|
||||
$middleware[$key] = (string) $value;
|
||||
}
|
||||
|
||||
$this->options['middleware'] = $middleware;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify middleware that should be removed from the resource routes.
|
||||
*
|
||||
* @param array|string $middleware
|
||||
* @return $this|array
|
||||
*/
|
||||
public function withoutMiddleware($middleware)
|
||||
{
|
||||
$this->options['excluded_middleware'] = array_merge(
|
||||
(array) ($this->options['excluded_middleware'] ?? []), Arr::wrap($middleware)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "where" constraints to the resource routes.
|
||||
*
|
||||
* @param mixed $wheres
|
||||
* @return \Illuminate\Routing\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function where($wheres)
|
||||
{
|
||||
$this->options['wheres'] = $wheres;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the singleton resource route.
|
||||
*
|
||||
* @return \Illuminate\Routing\RouteCollection
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registered = true;
|
||||
|
||||
return $this->registrar->singleton(
|
||||
$this->name, $this->controller, $this->options
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the object's destruction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (! $this->registered) {
|
||||
$this->register();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Illuminate\Contracts\Support\Responsable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pipeline\Pipeline as BasePipeline;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* This extended pipeline catches any exceptions that occur during each slice.
|
||||
@@ -18,60 +16,31 @@ use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
class Pipeline extends BasePipeline
|
||||
{
|
||||
/**
|
||||
* Get the final piece of the Closure onion.
|
||||
* Handles the value returned from each pipe before passing it to the next.
|
||||
*
|
||||
* @param \Closure $destination
|
||||
* @return \Closure
|
||||
* @param mixed $carry
|
||||
* @return mixed
|
||||
*/
|
||||
protected function prepareDestination(Closure $destination)
|
||||
protected function handleCarry($carry)
|
||||
{
|
||||
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));
|
||||
}
|
||||
};
|
||||
};
|
||||
return $carry instanceof Responsable
|
||||
? $carry->toResponse($this->getContainer()->make(Request::class))
|
||||
: $carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given exception.
|
||||
*
|
||||
* @param mixed $passable
|
||||
* @param \Exception $e
|
||||
* @param \Throwable $e
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function handleException($passable, Exception $e)
|
||||
protected function handleException($passable, Throwable $e)
|
||||
{
|
||||
if (! $this->container->bound(ExceptionHandler::class) || ! $passable instanceof Request) {
|
||||
if (! $this->container->bound(ExceptionHandler::class) ||
|
||||
! $passable instanceof Request) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@@ -81,7 +50,7 @@ class Pipeline extends BasePipeline
|
||||
|
||||
$response = $handler->render($passable, $e);
|
||||
|
||||
if (method_exists($response, 'withException')) {
|
||||
if (is_object($response) && method_exists($response, 'withException')) {
|
||||
$response->withException($e);
|
||||
}
|
||||
|
||||
|
||||
44
vendor/laravel/framework/src/Illuminate/Routing/RedirectController.php
vendored
Normal file
44
vendor/laravel/framework/src/Illuminate/Routing/RedirectController.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RedirectController extends Controller
|
||||
{
|
||||
/**
|
||||
* Invoke the controller method.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Routing\UrlGenerator $url
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function __invoke(Request $request, UrlGenerator $url)
|
||||
{
|
||||
$parameters = collect($request->route()->parameters());
|
||||
|
||||
$status = $parameters->get('status');
|
||||
|
||||
$destination = $parameters->get('destination');
|
||||
|
||||
$parameters->forget('status')->forget('destination');
|
||||
|
||||
$route = (new Route('GET', $destination, [
|
||||
'as' => 'laravel_route_redirect_destination',
|
||||
]))->bind($request);
|
||||
|
||||
$parameters = $parameters->only(
|
||||
$route->getCompiled()->getPathVariables()
|
||||
)->toArray();
|
||||
|
||||
$url = $url->toRoute($route, $parameters, false);
|
||||
|
||||
if (! str_starts_with($destination, '/') && str_starts_with($url, '/')) {
|
||||
$url = Str::after($url, '/');
|
||||
}
|
||||
|
||||
return new RedirectResponse($url, $status);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,12 @@ namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Session\Store as SessionStore;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
|
||||
class Redirector
|
||||
{
|
||||
use Macroable;
|
||||
|
||||
/**
|
||||
* The URL generator instance.
|
||||
*
|
||||
@@ -37,6 +40,8 @@ class Redirector
|
||||
*
|
||||
* @param int $status
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @deprecated Will be removed in a future Laravel version.
|
||||
*/
|
||||
public function home($status = 302)
|
||||
{
|
||||
@@ -46,7 +51,7 @@ class Redirector
|
||||
/**
|
||||
* Create a new redirect response to the previous location.
|
||||
*
|
||||
* @param int $status
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param mixed $fallback
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
@@ -59,7 +64,7 @@ class Redirector
|
||||
/**
|
||||
* Create a new redirect response to the current URI.
|
||||
*
|
||||
* @param int $status
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
@@ -72,14 +77,22 @@ class Redirector
|
||||
* 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
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param bool|null $secure
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function guest($path, $status = 302, $headers = [], $secure = null)
|
||||
{
|
||||
$this->session->put('url.intended', $this->generator->full());
|
||||
$request = $this->generator->getRequest();
|
||||
|
||||
$intended = $request->isMethod('GET') && $request->route() && ! $request->expectsJson()
|
||||
? $this->generator->full()
|
||||
: $this->generator->previous();
|
||||
|
||||
if ($intended) {
|
||||
$this->setIntendedUrl($intended);
|
||||
}
|
||||
|
||||
return $this->to($path, $status, $headers, $secure);
|
||||
}
|
||||
@@ -87,10 +100,10 @@ class Redirector
|
||||
/**
|
||||
* Create a new redirect response to the previously intended location.
|
||||
*
|
||||
* @param string $default
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param bool $secure
|
||||
* @param mixed $default
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param bool|null $secure
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function intended($default = '/', $status = 302, $headers = [], $secure = null)
|
||||
@@ -104,9 +117,9 @@ class Redirector
|
||||
* Create a new redirect response to the given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param bool $secure
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param bool|null $secure
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function to($path, $status = 302, $headers = [], $secure = null)
|
||||
@@ -118,8 +131,8 @@ class Redirector
|
||||
* Create a new redirect response to an external URL (no validation).
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function away($path, $status = 302, $headers = [])
|
||||
@@ -131,8 +144,8 @@ class Redirector
|
||||
* Create a new redirect response to the given HTTPS path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function secure($path, $status = 302, $headers = [])
|
||||
@@ -144,9 +157,9 @@ class Redirector
|
||||
* Create a new redirect response to a named route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param mixed $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function route($route, $parameters = [], $status = 302, $headers = [])
|
||||
@@ -154,13 +167,43 @@ class Redirector
|
||||
return $this->to($this->generator->route($route, $parameters), $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new redirect response to a signed named route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param mixed $parameters
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $expiration
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function signedRoute($route, $parameters = [], $expiration = null, $status = 302, $headers = [])
|
||||
{
|
||||
return $this->to($this->generator->signedRoute($route, $parameters, $expiration), $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new redirect response to a signed named route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $expiration
|
||||
* @param mixed $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function temporarySignedRoute($route, $expiration, $parameters = [], $status = 302, $headers = [])
|
||||
{
|
||||
return $this->to($this->generator->temporarySignedRoute($route, $expiration, $parameters), $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new redirect response to a controller action.
|
||||
*
|
||||
* @param string $action
|
||||
* @param array $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param string|array $action
|
||||
* @param mixed $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function action($action, $parameters = [], $status = 302, $headers = [])
|
||||
@@ -172,8 +215,8 @@ class Redirector
|
||||
* Create a new redirect response.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function createRedirect($path, $status, $headers)
|
||||
@@ -207,4 +250,27 @@ class Redirector
|
||||
{
|
||||
$this->session = $session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "intended" URL from the session.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getIntendedUrl()
|
||||
{
|
||||
return $this->session->get('url.intended');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the "intended" URL in the session.
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function setIntendedUrl($url)
|
||||
{
|
||||
$this->session->put('url.intended', $url);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ResourceRegistrar
|
||||
@@ -16,10 +17,17 @@ class ResourceRegistrar
|
||||
/**
|
||||
* The default actions for a resourceful controller.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $resourceDefaults = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy'];
|
||||
|
||||
/**
|
||||
* The default actions for a singleton resource controller.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $singletonResourceDefaults = ['show', 'edit', 'update'];
|
||||
|
||||
/**
|
||||
* The parameters set for this resource instance.
|
||||
*
|
||||
@@ -67,8 +75,8 @@ class ResourceRegistrar
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return void
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\RouteCollection
|
||||
*/
|
||||
public function register($name, $controller, array $options = [])
|
||||
{
|
||||
@@ -79,7 +87,7 @@ class ResourceRegistrar
|
||||
// If the resource name contains a slash, we will assume the developer wishes to
|
||||
// register these resource routes with a prefix so we will set that up out of
|
||||
// the box so they don't have to mess with it. Otherwise, we will continue.
|
||||
if (Str::contains($name, '/')) {
|
||||
if (str_contains($name, '/')) {
|
||||
$this->prefixedResource($name, $controller, $options);
|
||||
|
||||
return;
|
||||
@@ -92,9 +100,72 @@ class ResourceRegistrar
|
||||
|
||||
$defaults = $this->resourceDefaults;
|
||||
|
||||
foreach ($this->getResourceMethods($defaults, $options) as $m) {
|
||||
$this->{'addResource'.ucfirst($m)}($name, $base, $controller, $options);
|
||||
$collection = new RouteCollection;
|
||||
|
||||
$resourceMethods = $this->getResourceMethods($defaults, $options);
|
||||
|
||||
foreach ($resourceMethods as $m) {
|
||||
$route = $this->{'addResource'.ucfirst($m)}(
|
||||
$name, $base, $controller, $options
|
||||
);
|
||||
|
||||
if (isset($options['bindingFields'])) {
|
||||
$this->setResourceBindingFields($route, $options['bindingFields']);
|
||||
}
|
||||
|
||||
if (isset($options['trashed']) &&
|
||||
in_array($m, ! empty($options['trashed']) ? $options['trashed'] : array_intersect($resourceMethods, ['show', 'edit', 'update']))) {
|
||||
$route->withTrashed();
|
||||
}
|
||||
|
||||
$collection->add($route);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Route a singleton resource to a controller.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\RouteCollection
|
||||
*/
|
||||
public function singleton($name, $controller, array $options = [])
|
||||
{
|
||||
if (isset($options['parameters']) && ! isset($this->parameters)) {
|
||||
$this->parameters = $options['parameters'];
|
||||
}
|
||||
|
||||
// If the resource name contains a slash, we will assume the developer wishes to
|
||||
// register these singleton routes with a prefix so we will set that up out of
|
||||
// the box so they don't have to mess with it. Otherwise, we will continue.
|
||||
if (str_contains($name, '/')) {
|
||||
$this->prefixedSingleton($name, $controller, $options);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$defaults = $this->singletonResourceDefaults;
|
||||
|
||||
$collection = new RouteCollection;
|
||||
|
||||
$resourceMethods = $this->getResourceMethods($defaults, $options);
|
||||
|
||||
foreach ($resourceMethods as $m) {
|
||||
$route = $this->{'addSingleton'.ucfirst($m)}(
|
||||
$name, $controller, $options
|
||||
);
|
||||
|
||||
if (isset($options['bindingFields'])) {
|
||||
$this->setResourceBindingFields($route, $options['bindingFields']);
|
||||
}
|
||||
|
||||
$collection->add($route);
|
||||
}
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,12 +173,12 @@ class ResourceRegistrar
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
protected function prefixedResource($name, $controller, array $options)
|
||||
{
|
||||
list($name, $prefix) = $this->getResourcePrefix($name);
|
||||
[$name, $prefix] = $this->getResourcePrefix($name);
|
||||
|
||||
// We need to extract the base resource from the resource name. Nested resources
|
||||
// are supported in the framework, but we need to know what name to use for a
|
||||
@@ -119,6 +190,28 @@ class ResourceRegistrar
|
||||
return $this->router->group(compact('prefix'), $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a set of prefixed singleton routes.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
protected function prefixedSingleton($name, $controller, array $options)
|
||||
{
|
||||
[$name, $prefix] = $this->getResourcePrefix($name);
|
||||
|
||||
// We need to extract the base resource from the resource name. Nested resources
|
||||
// are supported in the framework, but we need to know what name to use for a
|
||||
// place-holder on the route parameters, which should be the base resources.
|
||||
$callback = function ($me) use ($name, $controller, $options) {
|
||||
$me->singleton($name, $controller, $options);
|
||||
};
|
||||
|
||||
return $this->router->group(compact('prefix'), $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the resource and prefix from a resource name.
|
||||
*
|
||||
@@ -146,13 +239,27 @@ class ResourceRegistrar
|
||||
*/
|
||||
protected function getResourceMethods($defaults, $options)
|
||||
{
|
||||
$methods = $defaults;
|
||||
|
||||
if (isset($options['only'])) {
|
||||
return array_intersect($defaults, (array) $options['only']);
|
||||
} elseif (isset($options['except'])) {
|
||||
return array_diff($defaults, (array) $options['except']);
|
||||
$methods = array_intersect($methods, (array) $options['only']);
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
if (isset($options['except'])) {
|
||||
$methods = array_diff($methods, (array) $options['except']);
|
||||
}
|
||||
|
||||
if (isset($options['creatable'])) {
|
||||
$methods = isset($options['apiSingleton'])
|
||||
? array_merge(['store', 'destroy'], $methods)
|
||||
: array_merge(['create', 'store', 'destroy'], $methods);
|
||||
|
||||
return $this->getResourceMethods(
|
||||
$methods, array_values(Arr::except($options, ['creatable']))
|
||||
);
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,13 +268,15 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceIndex($name, $base, $controller, $options)
|
||||
{
|
||||
$uri = $this->getResourceUri($name);
|
||||
|
||||
unset($options['missing']);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'index', $options);
|
||||
|
||||
return $this->router->get($uri, $action);
|
||||
@@ -179,13 +288,15 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceCreate($name, $base, $controller, $options)
|
||||
{
|
||||
$uri = $this->getResourceUri($name).'/'.static::$verbs['create'];
|
||||
|
||||
unset($options['missing']);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'create', $options);
|
||||
|
||||
return $this->router->get($uri, $action);
|
||||
@@ -197,13 +308,15 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceStore($name, $base, $controller, $options)
|
||||
{
|
||||
$uri = $this->getResourceUri($name);
|
||||
|
||||
unset($options['missing']);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'store', $options);
|
||||
|
||||
return $this->router->post($uri, $action);
|
||||
@@ -215,11 +328,13 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceShow($name, $base, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name).'/{'.$base.'}';
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'show', $options);
|
||||
@@ -233,11 +348,13 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceEdit($name, $base, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name).'/{'.$base.'}/'.static::$verbs['edit'];
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'edit', $options);
|
||||
@@ -251,11 +368,13 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceUpdate($name, $base, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name).'/{'.$base.'}';
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'update', $options);
|
||||
@@ -269,11 +388,13 @@ class ResourceRegistrar
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addResourceDestroy($name, $base, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name).'/{'.$base.'}';
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'destroy', $options);
|
||||
@@ -281,6 +402,153 @@ class ResourceRegistrar
|
||||
return $this->router->delete($uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the create method for a singleton route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addSingletonCreate($name, $controller, $options)
|
||||
{
|
||||
$uri = $this->getResourceUri($name).'/'.static::$verbs['create'];
|
||||
|
||||
unset($options['missing']);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'create', $options);
|
||||
|
||||
return $this->router->get($uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the store method for a singleton route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addSingletonStore($name, $controller, $options)
|
||||
{
|
||||
$uri = $this->getResourceUri($name);
|
||||
|
||||
unset($options['missing']);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'store', $options);
|
||||
|
||||
return $this->router->post($uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the show method for a singleton route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addSingletonShow($name, $controller, $options)
|
||||
{
|
||||
$uri = $this->getResourceUri($name);
|
||||
|
||||
unset($options['missing']);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'show', $options);
|
||||
|
||||
return $this->router->get($uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the edit method for a singleton route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addSingletonEdit($name, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name).'/'.static::$verbs['edit'];
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'edit', $options);
|
||||
|
||||
return $this->router->get($uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the update method for a singleton route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $base
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addSingletonUpdate($name, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'update', $options);
|
||||
|
||||
return $this->router->match(['PUT', 'PATCH'], $uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the destroy method for a singleton route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
protected function addSingletonDestroy($name, $controller, $options)
|
||||
{
|
||||
$name = $this->getShallowName($name, $options);
|
||||
|
||||
$uri = $this->getResourceUri($name);
|
||||
|
||||
$action = $this->getResourceAction($name, $controller, 'destroy', $options);
|
||||
|
||||
return $this->router->delete($uri, $action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name for a given resource with shallowness applied when applicable.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $options
|
||||
* @return string
|
||||
*/
|
||||
protected function getShallowName($name, $options)
|
||||
{
|
||||
return isset($options['shallow']) && $options['shallow']
|
||||
? last(explode('.', $name))
|
||||
: $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the route's binding fields if the resource is scoped.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param array $bindingFields
|
||||
* @return void
|
||||
*/
|
||||
protected function setResourceBindingFields($route, $bindingFields)
|
||||
{
|
||||
preg_match_all('/(?<={).*?(?=})/', $route->uri, $matches);
|
||||
|
||||
$fields = array_fill_keys($matches[0], null);
|
||||
|
||||
$route->setBindingFields(array_replace(
|
||||
$fields, array_intersect_key($bindingFields, $fields)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base resource URI for a given resource.
|
||||
*
|
||||
@@ -289,7 +557,7 @@ class ResourceRegistrar
|
||||
*/
|
||||
public function getResourceUri($resource)
|
||||
{
|
||||
if (! Str::contains($resource, '.')) {
|
||||
if (! str_contains($resource, '.')) {
|
||||
return $resource;
|
||||
}
|
||||
|
||||
@@ -306,7 +574,7 @@ class ResourceRegistrar
|
||||
/**
|
||||
* Get the URI for a nested resource segment array.
|
||||
*
|
||||
* @param array $segments
|
||||
* @param array $segments
|
||||
* @return string
|
||||
*/
|
||||
protected function getNestedResourceUri(array $segments)
|
||||
@@ -344,7 +612,7 @@ class ResourceRegistrar
|
||||
* @param string $resource
|
||||
* @param string $controller
|
||||
* @param string $method
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function getResourceAction($resource, $controller, $method, $options)
|
||||
@@ -357,6 +625,18 @@ class ResourceRegistrar
|
||||
$action['middleware'] = $options['middleware'];
|
||||
}
|
||||
|
||||
if (isset($options['excluded_middleware'])) {
|
||||
$action['excluded_middleware'] = $options['excluded_middleware'];
|
||||
}
|
||||
|
||||
if (isset($options['wheres'])) {
|
||||
$action['where'] = $options['wheres'];
|
||||
}
|
||||
|
||||
if (isset($options['missing'])) {
|
||||
$action['missing'] = $options['missing'];
|
||||
}
|
||||
|
||||
return $action;
|
||||
}
|
||||
|
||||
@@ -365,7 +645,7 @@ class ResourceRegistrar
|
||||
*
|
||||
* @param string $resource
|
||||
* @param string $method
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
* @return string
|
||||
*/
|
||||
protected function getResourceRouteName($resource, $method, $options)
|
||||
@@ -415,7 +695,7 @@ class ResourceRegistrar
|
||||
/**
|
||||
* Set the global parameter mapping.
|
||||
*
|
||||
* @param array $parameters
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*/
|
||||
public static function setParameters(array $parameters = [])
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
|
||||
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;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Exceptions\StreamedResponseException;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Throwable;
|
||||
|
||||
class ResponseFactory implements FactoryContract
|
||||
{
|
||||
@@ -43,9 +45,9 @@ class ResponseFactory implements FactoryContract
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new response from the application.
|
||||
* Create a new response instance.
|
||||
*
|
||||
* @param string $content
|
||||
* @param mixed $content
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\Response
|
||||
@@ -56,9 +58,21 @@ class ResponseFactory implements FactoryContract
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new view response from the application.
|
||||
* Create a new "no content" response.
|
||||
*
|
||||
* @param string $view
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function noContent($status = 204, array $headers = [])
|
||||
{
|
||||
return $this->make('', $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new response for a given view.
|
||||
*
|
||||
* @param string|array $view
|
||||
* @param array $data
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
@@ -66,11 +80,15 @@ class ResponseFactory implements FactoryContract
|
||||
*/
|
||||
public function view($view, $data = [], $status = 200, array $headers = [])
|
||||
{
|
||||
if (is_array($view)) {
|
||||
return $this->make($this->view->first($view, $data), $status, $headers);
|
||||
}
|
||||
|
||||
return $this->make($this->view->make($view, $data), $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new JSON response from the application.
|
||||
* Create a new JSON response instance.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param int $status
|
||||
@@ -84,7 +102,7 @@ class ResponseFactory implements FactoryContract
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new JSONP response from the application.
|
||||
* Create a new JSONP response instance.
|
||||
*
|
||||
* @param string $callback
|
||||
* @param mixed $data
|
||||
@@ -99,7 +117,7 @@ class ResponseFactory implements FactoryContract
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new streamed response from the application.
|
||||
* Create a new streamed response instance.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param int $status
|
||||
@@ -111,11 +129,43 @@ class ResponseFactory implements FactoryContract
|
||||
return new StreamedResponse($callback, $status, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new streamed response instance as a file download.
|
||||
*
|
||||
* @param \Closure $callback
|
||||
* @param string|null $name
|
||||
* @param array $headers
|
||||
* @param string|null $disposition
|
||||
* @return \Symfony\Component\HttpFoundation\StreamedResponse
|
||||
*/
|
||||
public function streamDownload($callback, $name = null, array $headers = [], $disposition = 'attachment')
|
||||
{
|
||||
$withWrappedException = function () use ($callback) {
|
||||
try {
|
||||
$callback();
|
||||
} catch (Throwable $e) {
|
||||
throw new StreamedResponseException($e);
|
||||
}
|
||||
};
|
||||
|
||||
$response = new StreamedResponse($withWrappedException, 200, $headers);
|
||||
|
||||
if (! is_null($name)) {
|
||||
$response->headers->set('Content-Disposition', $response->headers->makeDisposition(
|
||||
$disposition,
|
||||
$name,
|
||||
$this->fallbackName($name)
|
||||
));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new file download response.
|
||||
*
|
||||
* @param \SplFileInfo|string $file
|
||||
* @param string $name
|
||||
* @param string|null $name
|
||||
* @param array $headers
|
||||
* @param string|null $disposition
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
@@ -125,12 +175,23 @@ class ResponseFactory implements FactoryContract
|
||||
$response = new BinaryFileResponse($file, 200, $headers, true, $disposition);
|
||||
|
||||
if (! is_null($name)) {
|
||||
return $response->setContentDisposition($disposition, $name, str_replace('%', '', Str::ascii($name)));
|
||||
return $response->setContentDisposition($disposition, $name, $this->fallbackName($name));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the string to ASCII characters that are equivalent to the given name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
protected function fallbackName($name)
|
||||
{
|
||||
return str_replace('%', '', Str::ascii($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the raw contents of a binary file.
|
||||
*
|
||||
@@ -161,7 +222,7 @@ class ResponseFactory implements FactoryContract
|
||||
* Create a new redirect response to a named route.
|
||||
*
|
||||
* @param string $route
|
||||
* @param array $parameters
|
||||
* @param mixed $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
@@ -175,7 +236,7 @@ class ResponseFactory implements FactoryContract
|
||||
* Create a new redirect response to a controller action.
|
||||
*
|
||||
* @param string $action
|
||||
* @param array $parameters
|
||||
* @param mixed $parameters
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
|
||||
@@ -3,21 +3,26 @@
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Closure;
|
||||
use LogicException;
|
||||
use ReflectionFunction;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Routing\Matching\UriValidator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Contracts\CallableDispatcher;
|
||||
use Illuminate\Routing\Contracts\ControllerDispatcher as ControllerDispatcherContract;
|
||||
use Illuminate\Routing\Controllers\HasMiddleware;
|
||||
use Illuminate\Routing\Matching\HostValidator;
|
||||
use Illuminate\Routing\Matching\MethodValidator;
|
||||
use Illuminate\Routing\Matching\SchemeValidator;
|
||||
use Illuminate\Http\Exceptions\HttpResponseException;
|
||||
use Illuminate\Routing\Matching\UriValidator;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Laravel\SerializableClosure\SerializableClosure;
|
||||
use LogicException;
|
||||
use Symfony\Component\Routing\Route as SymfonyRoute;
|
||||
|
||||
class Route
|
||||
{
|
||||
use RouteDependencyResolverTrait;
|
||||
use CreatesRegularExpressionRouteConstraints, Macroable, RouteDependencyResolverTrait;
|
||||
|
||||
/**
|
||||
* The URI pattern the route responds to.
|
||||
@@ -40,6 +45,13 @@ class Route
|
||||
*/
|
||||
public $action;
|
||||
|
||||
/**
|
||||
* Indicates whether the route is a fallback route.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $isFallback = false;
|
||||
|
||||
/**
|
||||
* The controller instance.
|
||||
*
|
||||
@@ -64,7 +76,7 @@ class Route
|
||||
/**
|
||||
* The array of matched parameters.
|
||||
*
|
||||
* @var array
|
||||
* @var array|null
|
||||
*/
|
||||
public $parameters;
|
||||
|
||||
@@ -75,6 +87,34 @@ class Route
|
||||
*/
|
||||
public $parameterNames;
|
||||
|
||||
/**
|
||||
* The array of the matched parameters' original values.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $originalParameters;
|
||||
|
||||
/**
|
||||
* Indicates "trashed" models can be retrieved when resolving implicit model bindings for this route.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $withTrashedBindings = false;
|
||||
|
||||
/**
|
||||
* Indicates the maximum number of seconds the route should acquire a session lock for.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $lockSeconds;
|
||||
|
||||
/**
|
||||
* Indicates the maximum number of seconds the route should wait while attempting to acquire a session lock.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
protected $waitSeconds;
|
||||
|
||||
/**
|
||||
* The computed gathered middleware.
|
||||
*
|
||||
@@ -103,6 +143,13 @@ class Route
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* The fields that implicit binding should use for a given parameter.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $bindingFields = [];
|
||||
|
||||
/**
|
||||
* The validators used by the routes.
|
||||
*
|
||||
@@ -122,15 +169,13 @@ class Route
|
||||
{
|
||||
$this->uri = $uri;
|
||||
$this->methods = (array) $methods;
|
||||
$this->action = $this->parseAction($action);
|
||||
$this->action = Arr::except($this->parseAction($action), ['prefix']);
|
||||
|
||||
if (in_array('GET', $this->methods) && ! in_array('HEAD', $this->methods)) {
|
||||
$this->methods[] = 'HEAD';
|
||||
}
|
||||
|
||||
if (isset($this->action['prefix'])) {
|
||||
$this->prefix($this->action['prefix']);
|
||||
}
|
||||
$this->prefix(is_array($action) ? Arr::get($action, 'prefix') : '');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +218,7 @@ class Route
|
||||
*/
|
||||
protected function isControllerAction()
|
||||
{
|
||||
return is_string($this->action['uses']);
|
||||
return is_string($this->action['uses']) && ! $this->isSerializedClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,9 +230,21 @@ class Route
|
||||
{
|
||||
$callable = $this->action['uses'];
|
||||
|
||||
return $callable(...array_values($this->resolveMethodDependencies(
|
||||
$this->parametersWithoutNulls(), new ReflectionFunction($this->action['uses'])
|
||||
)));
|
||||
if ($this->isSerializedClosure()) {
|
||||
$callable = unserialize($this->action['uses'])->getClosure();
|
||||
}
|
||||
|
||||
return $this->container[CallableDispatcher::class]->dispatch($this, $callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route action is a serialized Closure.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isSerializedClosure()
|
||||
{
|
||||
return RouteAction::containsSerializedClosure($this->action);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,7 +256,7 @@ class Route
|
||||
*/
|
||||
protected function runController()
|
||||
{
|
||||
return (new ControllerDispatcher($this->container))->dispatch(
|
||||
return $this->controllerDispatcher()->dispatch(
|
||||
$this, $this->getController(), $this->getControllerMethod()
|
||||
);
|
||||
}
|
||||
@@ -211,15 +268,25 @@ class Route
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
$class = $this->parseControllerCallback()[0];
|
||||
|
||||
if (! $this->controller) {
|
||||
$this->controller = $this->container->make($class);
|
||||
$class = $this->getControllerClass();
|
||||
|
||||
$this->controller = $this->container->make(ltrim($class, '\\'));
|
||||
}
|
||||
|
||||
return $this->controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the controller class used for the route.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getControllerClass()
|
||||
{
|
||||
return $this->parseControllerCallback()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the controller method used for the route.
|
||||
*
|
||||
@@ -241,7 +308,18 @@ class Route
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route matches given request.
|
||||
* Flush the cached container instance on the route.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function flushController()
|
||||
{
|
||||
$this->computedMiddleware = null;
|
||||
$this->controller = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route matches a given request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param bool $includingMethod
|
||||
@@ -251,7 +329,7 @@ class Route
|
||||
{
|
||||
$this->compileRoute();
|
||||
|
||||
foreach ($this->getValidators() as $validator) {
|
||||
foreach (self::getValidators() as $validator) {
|
||||
if (! $includingMethod && $validator instanceof MethodValidator) {
|
||||
continue;
|
||||
}
|
||||
@@ -267,12 +345,12 @@ class Route
|
||||
/**
|
||||
* Compile the route into a Symfony CompiledRoute instance.
|
||||
*
|
||||
* @return void
|
||||
* @return \Symfony\Component\Routing\CompiledRoute
|
||||
*/
|
||||
protected function compileRoute()
|
||||
{
|
||||
if (! $this->compiled) {
|
||||
$this->compiled = (new RouteCompiler($this))->compile();
|
||||
$this->compiled = $this->toSymfonyRoute()->compile();
|
||||
}
|
||||
|
||||
return $this->compiled;
|
||||
@@ -291,6 +369,8 @@ class Route
|
||||
$this->parameters = (new RouteParameterBinder($this))
|
||||
->parameters($request);
|
||||
|
||||
$this->originalParameters = $this->parameters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -307,7 +387,7 @@ class Route
|
||||
/**
|
||||
* Determine a given parameter exists from the route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasParameter($name)
|
||||
@@ -323,19 +403,31 @@ class Route
|
||||
* Get a given parameter from the route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default
|
||||
* @return string|object
|
||||
* @param string|object|null $default
|
||||
* @return string|object|null
|
||||
*/
|
||||
public function parameter($name, $default = null)
|
||||
{
|
||||
return Arr::get($this->parameters(), $name, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get original value of a given parameter from the route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|null $default
|
||||
* @return string|null
|
||||
*/
|
||||
public function originalParameter($name, $default = null)
|
||||
{
|
||||
return Arr::get($this->originalParameters(), $name, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a parameter to the given value.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param string|object|null $value
|
||||
* @return void
|
||||
*/
|
||||
public function setParameter($name, $value)
|
||||
@@ -374,6 +466,22 @@ class Route
|
||||
throw new LogicException('Route is not bound.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key / value list of original parameters for the route.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function originalParameters()
|
||||
{
|
||||
if (isset($this->originalParameters)) {
|
||||
return $this->originalParameters;
|
||||
}
|
||||
|
||||
throw new LogicException('Route is not bound.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key / value list of parameters without null values.
|
||||
*
|
||||
@@ -381,9 +489,7 @@ class Route
|
||||
*/
|
||||
public function parametersWithoutNulls()
|
||||
{
|
||||
return array_filter($this->parameters(), function ($p) {
|
||||
return ! is_null($p);
|
||||
});
|
||||
return array_filter($this->parameters(), fn ($p) => ! is_null($p));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -407,22 +513,100 @@ class Route
|
||||
*/
|
||||
protected function compileParameterNames()
|
||||
{
|
||||
preg_match_all('/\{(.*?)\}/', $this->domain().$this->uri, $matches);
|
||||
preg_match_all('/\{(.*?)\}/', $this->getDomain().$this->uri, $matches);
|
||||
|
||||
return array_map(function ($m) {
|
||||
return trim($m, '?');
|
||||
}, $matches[1]);
|
||||
return array_map(fn ($m) => trim($m, '?'), $matches[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parameters that are listed in the route / controller signature.
|
||||
*
|
||||
* @param string|null $subClass
|
||||
* @param array $conditions
|
||||
* @return array
|
||||
*/
|
||||
public function signatureParameters($subClass = null)
|
||||
public function signatureParameters($conditions = [])
|
||||
{
|
||||
return RouteSignatureParameters::fromAction($this->action, $subClass);
|
||||
if (is_string($conditions)) {
|
||||
$conditions = ['subClass' => $conditions];
|
||||
}
|
||||
|
||||
return RouteSignatureParameters::fromAction($this->action, $conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the binding field for the given parameter.
|
||||
*
|
||||
* @param string|int $parameter
|
||||
* @return string|null
|
||||
*/
|
||||
public function bindingFieldFor($parameter)
|
||||
{
|
||||
$fields = is_int($parameter) ? array_values($this->bindingFields) : $this->bindingFields;
|
||||
|
||||
return $fields[$parameter] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the binding fields for the route.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function bindingFields()
|
||||
{
|
||||
return $this->bindingFields ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the binding fields for the route.
|
||||
*
|
||||
* @param array $bindingFields
|
||||
* @return $this
|
||||
*/
|
||||
public function setBindingFields(array $bindingFields)
|
||||
{
|
||||
$this->bindingFields = $bindingFields;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent parameter of the given parameter.
|
||||
*
|
||||
* @param string $parameter
|
||||
* @return string
|
||||
*/
|
||||
public function parentOfParameter($parameter)
|
||||
{
|
||||
$key = array_search($parameter, array_keys($this->parameters));
|
||||
|
||||
if ($key === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
return array_values($this->parameters)[$key - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow "trashed" models to be retrieved when resolving implicit model bindings for this route.
|
||||
*
|
||||
* @param bool $withTrashed
|
||||
* @return $this
|
||||
*/
|
||||
public function withTrashed($withTrashed = true)
|
||||
{
|
||||
$this->withTrashedBindings = $withTrashed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the route allows "trashed" models to be retrieved when resolving implicit model bindings.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function allowsTrashedBindings()
|
||||
{
|
||||
return $this->withTrashedBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -439,11 +623,24 @@ class Route
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default values for the route.
|
||||
*
|
||||
* @param array $defaults
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaults(array $defaults)
|
||||
{
|
||||
$this->defaults = $defaults;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a regular expression requirement on the route.
|
||||
*
|
||||
* @param array|string $name
|
||||
* @param string $expression
|
||||
* @param string|null $expression
|
||||
* @return $this
|
||||
*/
|
||||
public function where($name, $expression = null)
|
||||
@@ -473,7 +670,7 @@ class Route
|
||||
* @param array $wheres
|
||||
* @return $this
|
||||
*/
|
||||
protected function whereArray(array $wheres)
|
||||
public function setWheres(array $wheres)
|
||||
{
|
||||
foreach ($wheres as $name => $expression) {
|
||||
$this->where($name, $expression);
|
||||
@@ -482,6 +679,31 @@ class Route
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this route as a fallback route.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fallback()
|
||||
{
|
||||
$this->isFallback = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fallback value.
|
||||
*
|
||||
* @param bool $isFallback
|
||||
* @return $this
|
||||
*/
|
||||
public function setFallback($isFallback)
|
||||
{
|
||||
$this->isFallback = $isFallback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTTP verbs the route responds to.
|
||||
*
|
||||
@@ -522,12 +744,35 @@ class Route
|
||||
return in_array('https', $this->action, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set the domain for the route.
|
||||
*
|
||||
* @param string|null $domain
|
||||
* @return $this|string|null
|
||||
*/
|
||||
public function domain($domain = null)
|
||||
{
|
||||
if (is_null($domain)) {
|
||||
return $this->getDomain();
|
||||
}
|
||||
|
||||
$parsed = RouteUri::parse($domain);
|
||||
|
||||
$this->action['domain'] = $parsed->uri;
|
||||
|
||||
$this->bindingFields = array_merge(
|
||||
$this->bindingFields, $parsed->bindingFields
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the domain defined for the route.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function domain()
|
||||
public function getDomain()
|
||||
{
|
||||
return isset($this->action['domain'])
|
||||
? str_replace(['http://', 'https://'], '', $this->action['domain']) : null;
|
||||
@@ -536,11 +781,11 @@ class Route
|
||||
/**
|
||||
* Get the prefix of the route instance.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPrefix()
|
||||
{
|
||||
return isset($this->action['prefix']) ? $this->action['prefix'] : null;
|
||||
return $this->action['prefix'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,11 +796,26 @@ class Route
|
||||
*/
|
||||
public function prefix($prefix)
|
||||
{
|
||||
$prefix ??= '';
|
||||
|
||||
$this->updatePrefixOnAction($prefix);
|
||||
|
||||
$uri = rtrim($prefix, '/').'/'.ltrim($this->uri, '/');
|
||||
|
||||
$this->uri = trim($uri, '/');
|
||||
return $this->setUri($uri !== '/' ? trim($uri, '/') : $uri);
|
||||
}
|
||||
|
||||
return $this;
|
||||
/**
|
||||
* Update the "prefix" attribute on the action array.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @return void
|
||||
*/
|
||||
protected function updatePrefixOnAction($prefix)
|
||||
{
|
||||
if (! empty($newPrefix = trim(rtrim($prefix, '/').'/'.ltrim($this->action['prefix'] ?? '', '/'), '/'))) {
|
||||
$this->action['prefix'] = $newPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,19 +836,34 @@ class Route
|
||||
*/
|
||||
public function setUri($uri)
|
||||
{
|
||||
$this->uri = $uri;
|
||||
$this->uri = $this->parseUri($uri);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the route URI and normalize / store any implicit binding fields.
|
||||
*
|
||||
* @param string $uri
|
||||
* @return string
|
||||
*/
|
||||
protected function parseUri($uri)
|
||||
{
|
||||
$this->bindingFields = [];
|
||||
|
||||
return tap(RouteUri::parse($uri), function ($uri) {
|
||||
$this->bindingFields = $uri->bindingFields;
|
||||
})->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the route instance.
|
||||
*
|
||||
* @return string
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return isset($this->action['as']) ? $this->action['as'] : null;
|
||||
return $this->action['as'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -605,24 +880,38 @@ class Route
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the route's name matches the given name.
|
||||
* Determine whether the route's name matches the given patterns.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed ...$patterns
|
||||
* @return bool
|
||||
*/
|
||||
public function named($name)
|
||||
public function named(...$patterns)
|
||||
{
|
||||
return $this->getName() === $name;
|
||||
if (is_null($routeName = $this->getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($patterns as $pattern) {
|
||||
if (Str::is($pattern, $routeName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the handler for the route.
|
||||
*
|
||||
* @param \Closure|string $action
|
||||
* @param \Closure|array|string $action
|
||||
* @return $this
|
||||
*/
|
||||
public function uses($action)
|
||||
{
|
||||
if (is_array($action)) {
|
||||
$action = $action[0].'@'.$action[1];
|
||||
}
|
||||
|
||||
$action = is_string($action) ? $this->addGroupNamespaceToStringUses($action) : $action;
|
||||
|
||||
return $this->setAction(array_merge($this->action, $this->parseAction([
|
||||
@@ -641,7 +930,7 @@ class Route
|
||||
{
|
||||
$groupStack = last($this->router->getGroupStack());
|
||||
|
||||
if (isset($groupStack['namespace']) && strpos($action, '\\') !== 0) {
|
||||
if (isset($groupStack['namespace']) && ! str_starts_with($action, '\\')) {
|
||||
return $groupStack['namespace'].'\\'.$action;
|
||||
}
|
||||
|
||||
@@ -655,7 +944,7 @@ class Route
|
||||
*/
|
||||
public function getActionName()
|
||||
{
|
||||
return isset($this->action['controller']) ? $this->action['controller'] : 'Closure';
|
||||
return $this->action['controller'] ?? 'Closure';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,17 +954,18 @@ class Route
|
||||
*/
|
||||
public function getActionMethod()
|
||||
{
|
||||
return array_last(explode('@', $this->getActionName()));
|
||||
return Arr::last(explode('@', $this->getActionName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the action array for the route.
|
||||
* Get the action array or one of its properties for the route.
|
||||
*
|
||||
* @return array
|
||||
* @param string|null $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAction()
|
||||
public function getAction($key = null)
|
||||
{
|
||||
return $this->action;
|
||||
return Arr::get($this->action, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -688,6 +978,38 @@ class Route
|
||||
{
|
||||
$this->action = $action;
|
||||
|
||||
if (isset($this->action['domain'])) {
|
||||
$this->domain($this->action['domain']);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the action that should be taken on a missing model exception.
|
||||
*
|
||||
* @return \Closure|null
|
||||
*/
|
||||
public function getMissing()
|
||||
{
|
||||
$missing = $this->action['missing'] ?? null;
|
||||
|
||||
return is_string($missing) &&
|
||||
Str::startsWith($missing, [
|
||||
'O:47:"Laravel\\SerializableClosure\\SerializableClosure',
|
||||
]) ? unserialize($missing) : $missing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the callable that should be invoked on a missing model exception.
|
||||
*
|
||||
* @param \Closure $missing
|
||||
* @return $this
|
||||
*/
|
||||
public function missing($missing)
|
||||
{
|
||||
$this->action['missing'] = $missing;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -704,34 +1026,52 @@ class Route
|
||||
|
||||
$this->computedMiddleware = [];
|
||||
|
||||
return $this->computedMiddleware = array_unique(array_merge(
|
||||
return $this->computedMiddleware = Router::uniqueMiddleware(array_merge(
|
||||
$this->middleware(), $this->controllerMiddleware()
|
||||
), SORT_REGULAR);
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set the middlewares attached to the route.
|
||||
*
|
||||
* @param array|string|null $middleware
|
||||
* @param array|string|null $middleware
|
||||
* @return $this|array
|
||||
*/
|
||||
public function middleware($middleware = null)
|
||||
{
|
||||
if (is_null($middleware)) {
|
||||
return (array) Arr::get($this->action, 'middleware', []);
|
||||
return (array) ($this->action['middleware'] ?? []);
|
||||
}
|
||||
|
||||
if (is_string($middleware)) {
|
||||
if (! is_array($middleware)) {
|
||||
$middleware = func_get_args();
|
||||
}
|
||||
|
||||
foreach ($middleware as $index => $value) {
|
||||
$middleware[$index] = (string) $value;
|
||||
}
|
||||
|
||||
$this->action['middleware'] = array_merge(
|
||||
(array) Arr::get($this->action, 'middleware', []), $middleware
|
||||
(array) ($this->action['middleware'] ?? []), $middleware
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the "Authorize" / "can" middleware should be applied to the route with the given options.
|
||||
*
|
||||
* @param string $ability
|
||||
* @param array|string $models
|
||||
* @return $this
|
||||
*/
|
||||
public function can($ability, $models = [])
|
||||
{
|
||||
return empty($models)
|
||||
? $this->middleware(['can:'.$ability])
|
||||
: $this->middleware(['can:'.$ability.','.implode(',', Arr::wrap($models))]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the middleware for the route's controller.
|
||||
*
|
||||
@@ -743,9 +1083,168 @@ class Route
|
||||
return [];
|
||||
}
|
||||
|
||||
return ControllerDispatcher::getMiddleware(
|
||||
$this->getController(), $this->getControllerMethod()
|
||||
[$controllerClass, $controllerMethod] = [
|
||||
$this->getControllerClass(),
|
||||
$this->getControllerMethod(),
|
||||
];
|
||||
|
||||
if (is_a($controllerClass, HasMiddleware::class, true)) {
|
||||
return $this->staticallyProvidedControllerMiddleware(
|
||||
$controllerClass, $controllerMethod
|
||||
);
|
||||
}
|
||||
|
||||
if (method_exists($controllerClass, 'getMiddleware')) {
|
||||
return $this->controllerDispatcher()->getMiddleware(
|
||||
$this->getController(), $controllerMethod
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the statically provided controller middleware for the given class and method.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
* @return array
|
||||
*/
|
||||
protected function staticallyProvidedControllerMiddleware(string $class, string $method)
|
||||
{
|
||||
return collect($class::middleware())->reject(function ($middleware) use ($method) {
|
||||
return $this->controllerDispatcher()::methodExcludedByOptions(
|
||||
$method, ['only' => $middleware->only, 'except' => $middleware->except]
|
||||
);
|
||||
})->map->middleware->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify middleware that should be removed from the given route.
|
||||
*
|
||||
* @param array|string $middleware
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutMiddleware($middleware)
|
||||
{
|
||||
$this->action['excluded_middleware'] = array_merge(
|
||||
(array) ($this->action['excluded_middleware'] ?? []), Arr::wrap($middleware)
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the middleware should be removed from the route.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function excludedMiddleware()
|
||||
{
|
||||
return (array) ($this->action['excluded_middleware'] ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the route should enforce scoping of multiple implicit Eloquent bindings.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function scopeBindings()
|
||||
{
|
||||
$this->action['scope_bindings'] = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the route should not enforce scoping of multiple implicit Eloquent bindings.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutScopedBindings()
|
||||
{
|
||||
$this->action['scope_bindings'] = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route should enforce scoping of multiple implicit Eloquent bindings.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function enforcesScopedBindings()
|
||||
{
|
||||
return (bool) ($this->action['scope_bindings'] ?? false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the route should prevent scoping of multiple implicit Eloquent bindings.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function preventsScopedBindings()
|
||||
{
|
||||
return isset($this->action['scope_bindings']) && $this->action['scope_bindings'] === false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the route should not allow concurrent requests from the same session.
|
||||
*
|
||||
* @param int|null $lockSeconds
|
||||
* @param int|null $waitSeconds
|
||||
* @return $this
|
||||
*/
|
||||
public function block($lockSeconds = 10, $waitSeconds = 10)
|
||||
{
|
||||
$this->lockSeconds = $lockSeconds;
|
||||
$this->waitSeconds = $waitSeconds;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that the route should allow concurrent requests from the same session.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withoutBlocking()
|
||||
{
|
||||
return $this->block(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of seconds the route's session lock should be held for.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function locksFor()
|
||||
{
|
||||
return $this->lockSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum number of seconds to wait while attempting to acquire a session lock.
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function waitsFor()
|
||||
{
|
||||
return $this->waitSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dispatcher for the route's controller.
|
||||
*
|
||||
* @return \Illuminate\Routing\Contracts\ControllerDispatcher
|
||||
*/
|
||||
public function controllerDispatcher()
|
||||
{
|
||||
if ($this->container->bound(ControllerDispatcherContract::class)) {
|
||||
return $this->container->make(ControllerDispatcherContract::class);
|
||||
}
|
||||
|
||||
return new ControllerDispatcher($this->container);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -768,6 +1267,32 @@ class Route
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the route to a Symfony route.
|
||||
*
|
||||
* @return \Symfony\Component\Routing\Route
|
||||
*/
|
||||
public function toSymfonyRoute()
|
||||
{
|
||||
return new SymfonyRoute(
|
||||
preg_replace('/\{(\w+?)\?\}/', '{$1}', $this->uri()), $this->getOptionalParameterNames(),
|
||||
$this->wheres, ['utf8' => true],
|
||||
$this->getDomain() ?: '', [], $this->methods
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional parameter names for the route.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getOptionalParameterNames()
|
||||
{
|
||||
preg_match_all('/\{(\w+?)\?\}/', $this->uri(), $matches);
|
||||
|
||||
return isset($matches[1]) ? array_fill_keys($matches[1], null) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the compiled version of the route.
|
||||
*
|
||||
@@ -814,7 +1339,15 @@ class Route
|
||||
public function prepareForSerialization()
|
||||
{
|
||||
if ($this->action['uses'] instanceof Closure) {
|
||||
throw new LogicException("Unable to prepare route [{$this->uri}] for serialization. Uses Closure.");
|
||||
$this->action['uses'] = serialize(
|
||||
new SerializableClosure($this->action['uses'])
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($this->action['missing']) && $this->action['missing'] instanceof Closure) {
|
||||
$this->action['missing'] = serialize(
|
||||
new SerializableClosure($this->action['missing'])
|
||||
);
|
||||
}
|
||||
|
||||
$this->compileRoute();
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use LogicException;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Reflector;
|
||||
use Illuminate\Support\Str;
|
||||
use LogicException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class RouteAction
|
||||
@@ -28,8 +29,11 @@ class RouteAction
|
||||
// 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 (Reflector::isCallable($action, true)) {
|
||||
return ! is_array($action) ? ['uses' => $action] : [
|
||||
'uses' => $action[0].'@'.$action[1],
|
||||
'controller' => $action[0].'@'.$action[1],
|
||||
];
|
||||
}
|
||||
|
||||
// If no "uses" property has been set, we will dig through the array to find a
|
||||
@@ -39,7 +43,7 @@ class RouteAction
|
||||
$action['uses'] = static::findCallable($action);
|
||||
}
|
||||
|
||||
if (is_string($action['uses']) && ! Str::contains($action['uses'], '@')) {
|
||||
if (! static::containsSerializedClosure($action) && is_string($action['uses']) && ! str_contains($action['uses'], '@')) {
|
||||
$action['uses'] = static::makeInvokable($action['uses']);
|
||||
}
|
||||
|
||||
@@ -51,6 +55,8 @@ class RouteAction
|
||||
*
|
||||
* @param string $uri
|
||||
* @return array
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
protected static function missingAction($uri)
|
||||
{
|
||||
@@ -68,15 +74,17 @@ class RouteAction
|
||||
protected static function findCallable(array $action)
|
||||
{
|
||||
return Arr::first($action, function ($value, $key) {
|
||||
return is_callable($value) && is_numeric($key);
|
||||
return Reflector::isCallable($value) && is_numeric($key);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an action for an invokable controller.
|
||||
*
|
||||
* @param string $action
|
||||
* @param string $action
|
||||
* @return string
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
protected static function makeInvokable($action)
|
||||
{
|
||||
@@ -86,4 +94,17 @@ class RouteAction
|
||||
|
||||
return $action.'@__invoke';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given array actions contain a serialized Closure.
|
||||
*
|
||||
* @param array $action
|
||||
* @return bool
|
||||
*/
|
||||
public static function containsSerializedClosure(array $action)
|
||||
{
|
||||
return is_string($action['uses']) && Str::startsWith($action['uses'], [
|
||||
'O:47:"Laravel\\SerializableClosure\\SerializableClosure',
|
||||
]) !== false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class RouteBinding
|
||||
{
|
||||
@@ -37,11 +37,11 @@ class RouteBinding
|
||||
// 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');
|
||||
[$class, $method] = Str::parseCallback($binding, 'bind');
|
||||
|
||||
$callable = [$container->make($class), $method];
|
||||
|
||||
return call_user_func($callable, $value, $route);
|
||||
return $callable($value, $route);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ class RouteBinding
|
||||
* @param string $class
|
||||
* @param \Closure|null $callback
|
||||
* @return \Closure
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>
|
||||
*/
|
||||
public static function forModel($container, $class, $callback = null)
|
||||
{
|
||||
@@ -65,7 +67,7 @@ class RouteBinding
|
||||
// throw a not found exception otherwise we will return the instance.
|
||||
$instance = $container->make($class);
|
||||
|
||||
if ($model = $instance->where($instance->getRouteKeyName(), $value)->first()) {
|
||||
if ($model = $instance->resolveRouteBinding($value)) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
@@ -73,7 +75,7 @@ class RouteBinding
|
||||
// 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);
|
||||
return $callback($value);
|
||||
}
|
||||
|
||||
throw (new ModelNotFoundException)->setModel($class);
|
||||
|
||||
@@ -2,16 +2,11 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Countable;
|
||||
use ArrayIterator;
|
||||
use IteratorAggregate;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class RouteCollection implements Countable, IteratorAggregate
|
||||
class RouteCollection extends AbstractRouteCollection
|
||||
{
|
||||
/**
|
||||
* An array of the routes keyed by method.
|
||||
@@ -21,23 +16,23 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
protected $routes = [];
|
||||
|
||||
/**
|
||||
* An flattened array of all of the routes.
|
||||
* A flattened array of all of the routes.
|
||||
*
|
||||
* @var array
|
||||
* @var \Illuminate\Routing\Route[]
|
||||
*/
|
||||
protected $allRoutes = [];
|
||||
|
||||
/**
|
||||
* A look-up table of routes by their names.
|
||||
*
|
||||
* @var array
|
||||
* @var \Illuminate\Routing\Route[]
|
||||
*/
|
||||
protected $nameList = [];
|
||||
|
||||
/**
|
||||
* A look-up table of routes by controller action.
|
||||
*
|
||||
* @var array
|
||||
* @var \Illuminate\Routing\Route[]
|
||||
*/
|
||||
protected $actionList = [];
|
||||
|
||||
@@ -64,7 +59,7 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
*/
|
||||
protected function addToCollections($route)
|
||||
{
|
||||
$domainAndUri = $route->domain().$route->uri();
|
||||
$domainAndUri = $route->getDomain().$route->uri();
|
||||
|
||||
foreach ($route->methods() as $method) {
|
||||
$this->routes[$method][$domainAndUri] = $route;
|
||||
@@ -84,15 +79,15 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
// 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;
|
||||
if ($name = $route->getName()) {
|
||||
$this->nameList[$name] = $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.
|
||||
$action = $route->getAction();
|
||||
|
||||
if (isset($action['controller'])) {
|
||||
$this->addToActionList($action, $route);
|
||||
}
|
||||
@@ -152,6 +147,7 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Routing\Route
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function match(Request $request)
|
||||
@@ -163,99 +159,14 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
// 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)
|
||||
{
|
||||
return Arr::first($routes, 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);
|
||||
return $this->handleMatchedRoute($request, $route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get routes from the collection by method.
|
||||
*
|
||||
* @param string|null $method
|
||||
* @return array
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function get($method = null)
|
||||
{
|
||||
@@ -281,7 +192,7 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
*/
|
||||
public function getByName($name)
|
||||
{
|
||||
return isset($this->nameList[$name]) ? $this->nameList[$name] : null;
|
||||
return $this->nameList[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,13 +203,13 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
*/
|
||||
public function getByAction($action)
|
||||
{
|
||||
return isset($this->actionList[$action]) ? $this->actionList[$action] : null;
|
||||
return $this->actionList[$action] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the routes in the collection.
|
||||
*
|
||||
* @return array
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function getRoutes()
|
||||
{
|
||||
@@ -318,7 +229,7 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
/**
|
||||
* Get all of the routes keyed by their name.
|
||||
*
|
||||
* @return array
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function getRoutesByName()
|
||||
{
|
||||
@@ -326,22 +237,32 @@ class RouteCollection implements Countable, IteratorAggregate
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an iterator for the items.
|
||||
* Convert the collection to a Symfony RouteCollection instance.
|
||||
*
|
||||
* @return \ArrayIterator
|
||||
* @return \Symfony\Component\Routing\RouteCollection
|
||||
*/
|
||||
public function getIterator()
|
||||
public function toSymfonyRouteCollection()
|
||||
{
|
||||
return new ArrayIterator($this->getRoutes());
|
||||
$symfonyRoutes = parent::toSymfonyRouteCollection();
|
||||
|
||||
$this->refreshNameLookups();
|
||||
|
||||
return $symfonyRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of items in the collection.
|
||||
* Convert the collection to a CompiledRouteCollection instance.
|
||||
*
|
||||
* @return int
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
* @param \Illuminate\Container\Container $container
|
||||
* @return \Illuminate\Routing\CompiledRouteCollection
|
||||
*/
|
||||
public function count()
|
||||
public function toCompiledRouteCollection(Router $router, Container $container)
|
||||
{
|
||||
return count($this->getRoutes());
|
||||
['compiled' => $compiled, 'attributes' => $attributes] = $this->compile();
|
||||
|
||||
return (new CompiledRouteCollection($compiled, $attributes))
|
||||
->setRouter($router)
|
||||
->setContainer($container);
|
||||
}
|
||||
}
|
||||
|
||||
98
vendor/laravel/framework/src/Illuminate/Routing/RouteCollectionInterface.php
vendored
Normal file
98
vendor/laravel/framework/src/Illuminate/Routing/RouteCollectionInterface.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
interface RouteCollectionInterface
|
||||
{
|
||||
/**
|
||||
* Add a Route instance to the collection.
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @return \Illuminate\Routing\Route
|
||||
*/
|
||||
public function add(Route $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();
|
||||
|
||||
/**
|
||||
* Refresh the action look-up table.
|
||||
*
|
||||
* This is done in case any actions are overwritten with new controllers.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function refreshActionLookups();
|
||||
|
||||
/**
|
||||
* Find the first route matching a given request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Routing\Route
|
||||
*
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
|
||||
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
||||
*/
|
||||
public function match(Request $request);
|
||||
|
||||
/**
|
||||
* Get routes from the collection by method.
|
||||
*
|
||||
* @param string|null $method
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function get($method = null);
|
||||
|
||||
/**
|
||||
* Determine if the route collection contains a given named route.
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNamedRoute($name);
|
||||
|
||||
/**
|
||||
* Get a route instance by its name.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
public function getByName($name);
|
||||
|
||||
/**
|
||||
* Get a route instance by its controller action.
|
||||
*
|
||||
* @param string $action
|
||||
* @return \Illuminate\Routing\Route|null
|
||||
*/
|
||||
public function getByAction($action);
|
||||
|
||||
/**
|
||||
* Get all of the routes in the collection.
|
||||
*
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function getRoutes();
|
||||
|
||||
/**
|
||||
* Get all of the routes keyed by their HTTP verb / method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRoutesByMethod();
|
||||
|
||||
/**
|
||||
* Get all of the routes keyed by their name.
|
||||
*
|
||||
* @return \Illuminate\Routing\Route[]
|
||||
*/
|
||||
public function getRoutesByName();
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?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->domain() ?: '')
|
||||
)->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) : [];
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Reflector;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunctionAbstract;
|
||||
use ReflectionMethod;
|
||||
use ReflectionParameter;
|
||||
use Illuminate\Support\Arr;
|
||||
use ReflectionFunctionAbstract;
|
||||
use stdClass;
|
||||
|
||||
trait RouteDependencyResolverTrait
|
||||
{
|
||||
@@ -41,12 +44,12 @@ trait RouteDependencyResolverTrait
|
||||
|
||||
$values = array_values($parameters);
|
||||
|
||||
foreach ($reflector->getParameters() as $key => $parameter) {
|
||||
$instance = $this->transformDependency(
|
||||
$parameter, $parameters
|
||||
);
|
||||
$skippableValue = new stdClass;
|
||||
|
||||
if (! is_null($instance)) {
|
||||
foreach ($reflector->getParameters() as $key => $parameter) {
|
||||
$instance = $this->transformDependency($parameter, $parameters, $skippableValue);
|
||||
|
||||
if ($instance !== $skippableValue) {
|
||||
$instanceCount++;
|
||||
|
||||
$this->spliceIntoParameters($parameters, $key, $instance);
|
||||
@@ -64,18 +67,25 @@ trait RouteDependencyResolverTrait
|
||||
*
|
||||
* @param \ReflectionParameter $parameter
|
||||
* @param array $parameters
|
||||
* @param object $skippableValue
|
||||
* @return mixed
|
||||
*/
|
||||
protected function transformDependency(ReflectionParameter $parameter, $parameters)
|
||||
protected function transformDependency(ReflectionParameter $parameter, $parameters, $skippableValue)
|
||||
{
|
||||
$class = $parameter->getClass();
|
||||
$className = Reflector::getParameterClassName($parameter);
|
||||
|
||||
// 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 $this->container->make($class->name);
|
||||
if ($className && ! $this->alreadyInParameters($className, $parameters)) {
|
||||
$isEnum = method_exists(ReflectionClass::class, 'isEnum') && (new ReflectionClass($className))->isEnum();
|
||||
|
||||
return $parameter->isDefaultValueAvailable()
|
||||
? ($isEnum ? $parameter->getDefaultValue() : null)
|
||||
: $this->container->make($className);
|
||||
}
|
||||
|
||||
return $skippableValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,9 +97,7 @@ trait RouteDependencyResolverTrait
|
||||
*/
|
||||
protected function alreadyInParameters($class, array $parameters)
|
||||
{
|
||||
return ! is_null(Arr::first($parameters, function ($value) use ($class) {
|
||||
return $value instanceof $class;
|
||||
}));
|
||||
return ! is_null(Arr::first($parameters, fn ($value) => $value instanceof $class));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
37
vendor/laravel/framework/src/Illuminate/Routing/RouteFileRegistrar.php
vendored
Normal file
37
vendor/laravel/framework/src/Illuminate/Routing/RouteFileRegistrar.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
class RouteFileRegistrar
|
||||
{
|
||||
/**
|
||||
* The router instance.
|
||||
*
|
||||
* @var \Illuminate\Routing\Router
|
||||
*/
|
||||
protected $router;
|
||||
|
||||
/**
|
||||
* Create a new route file registrar instance.
|
||||
*
|
||||
* @param \Illuminate\Routing\Router $router
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Router $router)
|
||||
{
|
||||
$this->router = $router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require the given routes file.
|
||||
*
|
||||
* @param string $routes
|
||||
* @return void
|
||||
*/
|
||||
public function register($routes)
|
||||
{
|
||||
$router = $this->router;
|
||||
|
||||
require $routes;
|
||||
}
|
||||
}
|
||||
@@ -11,17 +11,22 @@ class RouteGroup
|
||||
*
|
||||
* @param array $new
|
||||
* @param array $old
|
||||
* @param bool $prependExistingPrefix
|
||||
* @return array
|
||||
*/
|
||||
public static function merge($new, $old)
|
||||
public static function merge($new, $old, $prependExistingPrefix = true)
|
||||
{
|
||||
if (isset($new['domain'])) {
|
||||
unset($old['domain']);
|
||||
}
|
||||
|
||||
if (isset($new['controller'])) {
|
||||
unset($old['controller']);
|
||||
}
|
||||
|
||||
$new = array_merge(static::formatAs($new, $old), [
|
||||
'namespace' => static::formatNamespace($new, $old),
|
||||
'prefix' => static::formatPrefix($new, $old),
|
||||
'prefix' => static::formatPrefix($new, $old, $prependExistingPrefix),
|
||||
'where' => static::formatWhere($new, $old),
|
||||
]);
|
||||
|
||||
@@ -40,12 +45,12 @@ class RouteGroup
|
||||
protected static function formatNamespace($new, $old)
|
||||
{
|
||||
if (isset($new['namespace'])) {
|
||||
return isset($old['namespace'])
|
||||
return isset($old['namespace']) && ! str_starts_with($new['namespace'], '\\')
|
||||
? trim($old['namespace'], '\\').'\\'.trim($new['namespace'], '\\')
|
||||
: trim($new['namespace'], '\\');
|
||||
}
|
||||
|
||||
return isset($old['namespace']) ? $old['namespace'] : null;
|
||||
return $old['namespace'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,13 +58,18 @@ class RouteGroup
|
||||
*
|
||||
* @param array $new
|
||||
* @param array $old
|
||||
* @param bool $prependExistingPrefix
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function formatPrefix($new, $old)
|
||||
protected static function formatPrefix($new, $old, $prependExistingPrefix = true)
|
||||
{
|
||||
$old = Arr::get($old, 'prefix');
|
||||
$old = $old['prefix'] ?? '';
|
||||
|
||||
return isset($new['prefix']) ? trim($old, '/').'/'.trim($new['prefix'], '/') : $old;
|
||||
if ($prependExistingPrefix) {
|
||||
return isset($new['prefix']) ? trim($old, '/').'/'.trim($new['prefix'], '/') : $old;
|
||||
} else {
|
||||
return isset($new['prefix']) ? trim($new['prefix'], '/').'/'.trim($old, '/') : $old;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,8 +82,8 @@ class RouteGroup
|
||||
protected static function formatWhere($new, $old)
|
||||
{
|
||||
return array_merge(
|
||||
isset($old['where']) ? $old['where'] : [],
|
||||
isset($new['where']) ? $new['where'] : []
|
||||
$old['where'] ?? [],
|
||||
$new['where'] ?? []
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,7 +97,7 @@ class RouteGroup
|
||||
protected static function formatAs($new, $old)
|
||||
{
|
||||
if (isset($old['as'])) {
|
||||
$new['as'] = $old['as'].Arr::get($new, 'as', '');
|
||||
$new['as'] = $old['as'].($new['as'] ?? '');
|
||||
}
|
||||
|
||||
return $new;
|
||||
|
||||
@@ -32,9 +32,6 @@ class RouteParameterBinder
|
||||
*/
|
||||
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
|
||||
@@ -106,7 +103,7 @@ class RouteParameterBinder
|
||||
protected function replaceDefaults(array $parameters)
|
||||
{
|
||||
foreach ($parameters as $key => $value) {
|
||||
$parameters[$key] = isset($value) ? $value : Arr::get($this->route->defaults, $key);
|
||||
$parameters[$key] = $value ?? Arr::get($this->route->defaults, $key);
|
||||
}
|
||||
|
||||
foreach ($this->route->defaults as $key => $value) {
|
||||
|
||||
@@ -2,12 +2,36 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Closure;
|
||||
use BadMethodCallException;
|
||||
use Closure;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Reflector;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @method \Illuminate\Routing\Route any(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\Route delete(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\Route get(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\Route options(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\Route patch(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\Route post(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\Route put(string $uri, \Closure|array|string|null $action = null)
|
||||
* @method \Illuminate\Routing\RouteRegistrar as(string $value)
|
||||
* @method \Illuminate\Routing\RouteRegistrar controller(string $controller)
|
||||
* @method \Illuminate\Routing\RouteRegistrar domain(string $value)
|
||||
* @method \Illuminate\Routing\RouteRegistrar middleware(array|string|null $middleware)
|
||||
* @method \Illuminate\Routing\RouteRegistrar name(string $value)
|
||||
* @method \Illuminate\Routing\RouteRegistrar namespace(string|null $value)
|
||||
* @method \Illuminate\Routing\RouteRegistrar prefix(string $prefix)
|
||||
* @method \Illuminate\Routing\RouteRegistrar scopeBindings()
|
||||
* @method \Illuminate\Routing\RouteRegistrar where(array $where)
|
||||
* @method \Illuminate\Routing\RouteRegistrar withoutMiddleware(array|string $middleware)
|
||||
* @method \Illuminate\Routing\RouteRegistrar withoutScopedBindings()
|
||||
*/
|
||||
class RouteRegistrar
|
||||
{
|
||||
use CreatesRegularExpressionRouteConstraints;
|
||||
|
||||
/**
|
||||
* The router instance.
|
||||
*
|
||||
@@ -25,7 +49,7 @@ class RouteRegistrar
|
||||
/**
|
||||
* The methods to dynamically pass through to the router.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $passthru = [
|
||||
'get', 'post', 'put', 'patch', 'delete', 'options', 'any',
|
||||
@@ -34,10 +58,19 @@ class RouteRegistrar
|
||||
/**
|
||||
* The attributes that can be set through this class.
|
||||
*
|
||||
* @var array
|
||||
* @var string[]
|
||||
*/
|
||||
protected $allowedAttributes = [
|
||||
'as', 'domain', 'middleware', 'name', 'namespace', 'prefix',
|
||||
'as',
|
||||
'controller',
|
||||
'domain',
|
||||
'middleware',
|
||||
'name',
|
||||
'namespace',
|
||||
'prefix',
|
||||
'scopeBindings',
|
||||
'where',
|
||||
'withoutMiddleware',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -47,6 +80,8 @@ class RouteRegistrar
|
||||
*/
|
||||
protected $aliases = [
|
||||
'name' => 'as',
|
||||
'scopeBindings' => 'scope_bindings',
|
||||
'withoutMiddleware' => 'excluded_middleware',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -75,7 +110,21 @@ class RouteRegistrar
|
||||
throw new InvalidArgumentException("Attribute [{$key}] does not exist.");
|
||||
}
|
||||
|
||||
$this->attributes[array_get($this->aliases, $key, $key)] = $value;
|
||||
if ($key === 'middleware') {
|
||||
foreach ($value as $index => $middleware) {
|
||||
$value[$index] = (string) $middleware;
|
||||
}
|
||||
}
|
||||
|
||||
$attributeKey = Arr::get($this->aliases, $key, $key);
|
||||
|
||||
if ($key === 'withoutMiddleware') {
|
||||
$value = array_merge(
|
||||
(array) ($this->attributes[$attributeKey] ?? []), Arr::wrap($value)
|
||||
);
|
||||
}
|
||||
|
||||
$this->attributes[$attributeKey] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -86,22 +135,63 @@ class RouteRegistrar
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return void
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function resource($name, $controller, array $options = [])
|
||||
{
|
||||
$this->router->resource($name, $controller, $this->attributes + $options);
|
||||
return $this->router->resource($name, $controller, $this->attributes + $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route an API resource to a controller.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\PendingResourceRegistration
|
||||
*/
|
||||
public function apiResource($name, $controller, array $options = [])
|
||||
{
|
||||
return $this->router->apiResource($name, $controller, $this->attributes + $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route a singleton resource to a controller.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function singleton($name, $controller, array $options = [])
|
||||
{
|
||||
return $this->router->singleton($name, $controller, $this->attributes + $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Route an API singleton resource to a controller.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $controller
|
||||
* @param array $options
|
||||
* @return \Illuminate\Routing\PendingSingletonResourceRegistration
|
||||
*/
|
||||
public function apiSingleton($name, $controller, array $options = [])
|
||||
{
|
||||
return $this->router->apiSingleton($name, $controller, $this->attributes + $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a route group with shared attributes.
|
||||
*
|
||||
* @param \Closure|string $callback
|
||||
* @return void
|
||||
* @return $this
|
||||
*/
|
||||
public function group($callback)
|
||||
{
|
||||
$this->router->group($this->attributes, $callback);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,6 +240,18 @@ class RouteRegistrar
|
||||
$action = ['uses' => $action];
|
||||
}
|
||||
|
||||
if (is_array($action) &&
|
||||
! Arr::isAssoc($action) &&
|
||||
Reflector::isCallable($action)) {
|
||||
if (strncmp($action[0], '\\', 1)) {
|
||||
$action[0] = '\\'.$action[0];
|
||||
}
|
||||
$action = [
|
||||
'uses' => $action[0].'@'.$action[1],
|
||||
'controller' => $action[0].'@'.$action[1],
|
||||
];
|
||||
}
|
||||
|
||||
return array_merge($this->attributes, $action);
|
||||
}
|
||||
|
||||
@@ -159,6 +261,8 @@ class RouteRegistrar
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return \Illuminate\Routing\Route|$this
|
||||
*
|
||||
* @throws \BadMethodCallException
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
@@ -167,9 +271,15 @@ class RouteRegistrar
|
||||
}
|
||||
|
||||
if (in_array($method, $this->allowedAttributes)) {
|
||||
return $this->attribute($method, $parameters[0]);
|
||||
if ($method === 'middleware') {
|
||||
return $this->attribute($method, is_array($parameters[0]) ? $parameters[0] : $parameters);
|
||||
}
|
||||
|
||||
return $this->attribute($method, array_key_exists(0, $parameters) ? $parameters[0] : true);
|
||||
}
|
||||
|
||||
throw new BadMethodCallException("Method [{$method}] does not exist.");
|
||||
throw new BadMethodCallException(sprintf(
|
||||
'Method %s::%s does not exist.', static::class, $method
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use ReflectionMethod;
|
||||
use ReflectionFunction;
|
||||
use Illuminate\Support\Reflector;
|
||||
use Illuminate\Support\Str;
|
||||
use ReflectionFunction;
|
||||
use ReflectionMethod;
|
||||
|
||||
class RouteSignatureParameters
|
||||
{
|
||||
@@ -12,18 +13,24 @@ class RouteSignatureParameters
|
||||
* Extract the route action's signature parameters.
|
||||
*
|
||||
* @param array $action
|
||||
* @param string $subClass
|
||||
* @param array $conditions
|
||||
* @return array
|
||||
*/
|
||||
public static function fromAction(array $action, $subClass = null)
|
||||
public static function fromAction(array $action, $conditions = [])
|
||||
{
|
||||
$parameters = is_string($action['uses'])
|
||||
? static::fromClassMethodString($action['uses'])
|
||||
: (new ReflectionFunction($action['uses']))->getParameters();
|
||||
$callback = RouteAction::containsSerializedClosure($action)
|
||||
? unserialize($action['uses'])->getClosure()
|
||||
: $action['uses'];
|
||||
|
||||
return is_null($subClass) ? $parameters : array_filter($parameters, function ($p) use ($subClass) {
|
||||
return $p->getClass() && $p->getClass()->isSubclassOf($subClass);
|
||||
});
|
||||
$parameters = is_string($callback)
|
||||
? static::fromClassMethodString($callback)
|
||||
: (new ReflectionFunction($callback))->getParameters();
|
||||
|
||||
return match (true) {
|
||||
! empty($conditions['subClass']) => array_filter($parameters, fn ($p) => Reflector::isParameterSubclassOf($p, $conditions['subClass'])),
|
||||
! empty($conditions['backedEnum']) => array_filter($parameters, fn ($p) => Reflector::isParameterBackedEnumWithStringBackingType($p)),
|
||||
default => $parameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,9 +41,9 @@ class RouteSignatureParameters
|
||||
*/
|
||||
protected static function fromClassMethodString($uses)
|
||||
{
|
||||
list($class, $method) = Str::parseCallback($uses);
|
||||
[$class, $method] = Str::parseCallback($uses);
|
||||
|
||||
if (! method_exists($class, $method) && is_callable($class, $method)) {
|
||||
if (! method_exists($class, $method) && Reflector::isCallable($class, $method)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
62
vendor/laravel/framework/src/Illuminate/Routing/RouteUri.php
vendored
Normal file
62
vendor/laravel/framework/src/Illuminate/Routing/RouteUri.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
class RouteUri
|
||||
{
|
||||
/**
|
||||
* The route URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $uri;
|
||||
|
||||
/**
|
||||
* The fields that should be used when resolving bindings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $bindingFields = [];
|
||||
|
||||
/**
|
||||
* Create a new route URI instance.
|
||||
*
|
||||
* @param string $uri
|
||||
* @param array $bindingFields
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $uri, array $bindingFields = [])
|
||||
{
|
||||
$this->uri = $uri;
|
||||
$this->bindingFields = $bindingFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given URI.
|
||||
*
|
||||
* @param string $uri
|
||||
* @return static
|
||||
*/
|
||||
public static function parse($uri)
|
||||
{
|
||||
preg_match_all('/\{([\w\:]+?)\??\}/', $uri, $matches);
|
||||
|
||||
$bindingFields = [];
|
||||
|
||||
foreach ($matches[0] as $match) {
|
||||
if (! str_contains($match, ':')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$segments = explode(':', trim($match, '{}?'));
|
||||
|
||||
$bindingFields[$segments[0]] = $segments[1];
|
||||
|
||||
$uri = str_contains($match, '?')
|
||||
? str_replace($match, '{'.$segments[0].'?}', $uri)
|
||||
: str_replace($match, '{'.$segments[0].'}', $uri);
|
||||
}
|
||||
|
||||
return new static($uri, $bindingFields);
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,15 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Routing\Exceptions\UrlGenerationException;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class RouteUrlGenerator
|
||||
{
|
||||
/**
|
||||
* The URL generator instance.
|
||||
*
|
||||
* @param \Illuminate\Routing\UrlGenerator
|
||||
* @var \Illuminate\Routing\UrlGenerator
|
||||
*/
|
||||
protected $url;
|
||||
|
||||
@@ -83,11 +82,12 @@ class RouteUrlGenerator
|
||||
// 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)
|
||||
$this->replaceRouteParameters($route->uri(), $parameters),
|
||||
$route
|
||||
), $parameters);
|
||||
|
||||
if (preg_match('/\{.*?\}/', $uri)) {
|
||||
throw UrlGenerationException::forMissingParameters($route);
|
||||
if (preg_match_all('/{(.*?)}/', $uri, $matchedMissingParameters)) {
|
||||
throw UrlGenerationException::forMissingParameters($route, $matchedMissingParameters[1]);
|
||||
}
|
||||
|
||||
// Once we have ensured that there are no missing parameters in the URI we will encode
|
||||
@@ -96,7 +96,13 @@ class RouteUrlGenerator
|
||||
$uri = strtr(rawurlencode($uri), $this->dontEncode);
|
||||
|
||||
if (! $absolute) {
|
||||
return '/'.ltrim(str_replace($root, '', $uri), '/');
|
||||
$uri = preg_replace('#^(//|[^/?])+#', '', $uri);
|
||||
|
||||
if ($base = $this->request->getBaseUrl()) {
|
||||
$uri = preg_replace('#^'.$base.'#i', '', $uri);
|
||||
}
|
||||
|
||||
return '/'.ltrim($uri, '/');
|
||||
}
|
||||
|
||||
return $uri;
|
||||
@@ -111,7 +117,7 @@ class RouteUrlGenerator
|
||||
*/
|
||||
protected function getRouteDomain($route, &$parameters)
|
||||
{
|
||||
return $route->domain() ? $this->formatDomain($route, $parameters) : null;
|
||||
return $route->getDomain() ? $this->formatDomain($route, $parameters) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +130,7 @@ class RouteUrlGenerator
|
||||
protected function formatDomain($route, &$parameters)
|
||||
{
|
||||
return $this->addPortToDomain(
|
||||
$this->getRouteScheme($route).$route->domain()
|
||||
$this->getRouteScheme($route).$route->getDomain()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -140,9 +146,9 @@ class RouteUrlGenerator
|
||||
return 'http://';
|
||||
} elseif ($route->httpsOnly()) {
|
||||
return 'https://';
|
||||
} else {
|
||||
return $this->url->formatScheme(null);
|
||||
}
|
||||
|
||||
return $this->url->formatScheme();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,9 +196,12 @@ class RouteUrlGenerator
|
||||
$path = $this->replaceNamedParameters($path, $parameters);
|
||||
|
||||
$path = preg_replace_callback('/\{.*?\}/', function ($match) use (&$parameters) {
|
||||
return (empty($parameters) && ! Str::endsWith($match[0], '?}'))
|
||||
// Reset only the numeric keys...
|
||||
$parameters = array_merge($parameters);
|
||||
|
||||
return (! isset($parameters[0]) && ! str_ends_with($match[0], '?}'))
|
||||
? $match[0]
|
||||
: array_shift($parameters);
|
||||
: Arr::pull($parameters, 0);
|
||||
}, $path);
|
||||
|
||||
return trim(preg_replace('/\{.*?\?\}/', '', $path), '/');
|
||||
@@ -207,14 +216,16 @@ class RouteUrlGenerator
|
||||
*/
|
||||
protected function replaceNamedParameters($path, &$parameters)
|
||||
{
|
||||
return preg_replace_callback('/\{(.*?)\??\}/', function ($m) use (&$parameters) {
|
||||
if (isset($parameters[$m[1]])) {
|
||||
return preg_replace_callback('/\{(.*?)(\?)?\}/', function ($m) use (&$parameters) {
|
||||
if (isset($parameters[$m[1]]) && $parameters[$m[1]] !== '') {
|
||||
return Arr::pull($parameters, $m[1]);
|
||||
} elseif (isset($this->defaultParameters[$m[1]])) {
|
||||
return $this->defaultParameters[$m[1]];
|
||||
} else {
|
||||
return $m[0];
|
||||
} elseif (isset($parameters[$m[1]])) {
|
||||
Arr::pull($parameters, $m[1]);
|
||||
}
|
||||
|
||||
return $m[0];
|
||||
}, $path);
|
||||
}
|
||||
|
||||
@@ -250,11 +261,11 @@ class RouteUrlGenerator
|
||||
// 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) {
|
||||
if (count($parameters) === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$query = http_build_query(
|
||||
$query = Arr::query(
|
||||
$keyed = $this->getStringParameters($parameters)
|
||||
);
|
||||
|
||||
@@ -267,7 +278,9 @@ class RouteUrlGenerator
|
||||
);
|
||||
}
|
||||
|
||||
return '?'.trim($query, '&');
|
||||
$query = trim($query, '&');
|
||||
|
||||
return $query === '' ? '' : "?{$query}";
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,13 +2,18 @@
|
||||
|
||||
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\Container\BindingResolutionException;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory as ResponseFactoryContract;
|
||||
use Illuminate\Contracts\Routing\UrlGenerator as UrlGeneratorContract;
|
||||
use Illuminate\Contracts\View\Factory as ViewFactoryContract;
|
||||
use Illuminate\Routing\Contracts\CallableDispatcher as CallableDispatcherContract;
|
||||
use Illuminate\Routing\Contracts\ControllerDispatcher as ControllerDispatcherContract;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Nyholm\Psr7\Response as PsrResponse;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
|
||||
|
||||
class RoutingServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -20,16 +25,13 @@ class RoutingServiceProvider extends ServiceProvider
|
||||
public function register()
|
||||
{
|
||||
$this->registerRouter();
|
||||
|
||||
$this->registerUrlGenerator();
|
||||
|
||||
$this->registerRedirector();
|
||||
|
||||
$this->registerPsrRequest();
|
||||
|
||||
$this->registerPsrResponse();
|
||||
|
||||
$this->registerResponseFactory();
|
||||
$this->registerCallableDispatcher();
|
||||
$this->registerControllerDispatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,14 +61,23 @@ class RoutingServiceProvider extends ServiceProvider
|
||||
// and all the registered routes will be available to the generator.
|
||||
$app->instance('routes', $routes);
|
||||
|
||||
$url = new UrlGenerator(
|
||||
return new UrlGenerator(
|
||||
$routes, $app->rebinding(
|
||||
'request', $this->requestRebinder()
|
||||
)
|
||||
), $app['config']['app.asset_url']
|
||||
);
|
||||
});
|
||||
|
||||
$this->app->extend('url', function (UrlGeneratorContract $url, $app) {
|
||||
// Next we will set a few service resolvers on the URL generator so it can
|
||||
// get the information it needs to function. This just provides some of
|
||||
// the convenience features to this URL generator like "signed" URLs.
|
||||
$url->setSessionResolver(function () {
|
||||
return $this->app['session'];
|
||||
return $this->app['session'] ?? null;
|
||||
});
|
||||
|
||||
$url->setKeyResolver(function () {
|
||||
return $this->app->make('config')->get('app.key');
|
||||
});
|
||||
|
||||
// If the route collection is "rebound", for example, when the routes stay
|
||||
@@ -117,11 +128,20 @@ class RoutingServiceProvider extends ServiceProvider
|
||||
* Register a binding for the PSR-7 request implementation.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function registerPsrRequest()
|
||||
{
|
||||
$this->app->bind(ServerRequestInterface::class, function ($app) {
|
||||
return (new DiactorosFactory)->createRequest($app->make('request'));
|
||||
if (class_exists(Psr17Factory::class) && class_exists(PsrHttpFactory::class)) {
|
||||
$psr17Factory = new Psr17Factory;
|
||||
|
||||
return (new PsrHttpFactory($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory))
|
||||
->createRequest($app->make('request'));
|
||||
}
|
||||
|
||||
throw new BindingResolutionException('Unable to resolve PSR request. Please install the symfony/psr-http-message-bridge and nyholm/psr7 packages.');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -129,11 +149,17 @@ class RoutingServiceProvider extends ServiceProvider
|
||||
* Register a binding for the PSR-7 response implementation.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Container\BindingResolutionException
|
||||
*/
|
||||
protected function registerPsrResponse()
|
||||
{
|
||||
$this->app->bind(ResponseInterface::class, function ($app) {
|
||||
return new PsrResponse();
|
||||
$this->app->bind(ResponseInterface::class, function () {
|
||||
if (class_exists(PsrResponse::class)) {
|
||||
return new PsrResponse;
|
||||
}
|
||||
|
||||
throw new BindingResolutionException('Unable to resolve PSR response. Please install the nyholm/psr7 package.');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,4 +174,28 @@ class RoutingServiceProvider extends ServiceProvider
|
||||
return new ResponseFactory($app[ViewFactoryContract::class], $app['redirect']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the callable dispatcher.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerCallableDispatcher()
|
||||
{
|
||||
$this->app->singleton(CallableDispatcherContract::class, function ($app) {
|
||||
return new CallableDispatcher($app);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the controller dispatcher.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function registerControllerDispatcher()
|
||||
{
|
||||
$this->app->singleton(ControllerDispatcherContract::class, function ($app) {
|
||||
return new ControllerDispatcher($app);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class SortedMiddleware extends Collection
|
||||
* Create a new Sorted Middleware container.
|
||||
*
|
||||
* @param array $priorityMap
|
||||
* @param array|Collection $middlewares
|
||||
* @param \Illuminate\Support\Collection|array $middlewares
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $priorityMap, $middlewares)
|
||||
@@ -40,32 +40,67 @@ class SortedMiddleware extends Collection
|
||||
continue;
|
||||
}
|
||||
|
||||
$stripped = head(explode(':', $middleware));
|
||||
|
||||
if (in_array($stripped, $priorityMap)) {
|
||||
$priorityIndex = array_search($stripped, $priorityMap);
|
||||
$priorityIndex = $this->priorityMapIndex($priorityMap, $middleware);
|
||||
|
||||
if (! is_null($priorityIndex)) {
|
||||
// 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)
|
||||
)
|
||||
$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.
|
||||
} else {
|
||||
$lastIndex = $index;
|
||||
$lastPriorityIndex = $priorityIndex;
|
||||
}
|
||||
$lastIndex = $index;
|
||||
|
||||
$lastPriorityIndex = $priorityIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($middlewares, SORT_REGULAR));
|
||||
return Router::uniqueMiddleware($middlewares);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the priority map index of the middleware.
|
||||
*
|
||||
* @param array $priorityMap
|
||||
* @param string $middleware
|
||||
* @return int|null
|
||||
*/
|
||||
protected function priorityMapIndex($priorityMap, $middleware)
|
||||
{
|
||||
foreach ($this->middlewareNames($middleware) as $name) {
|
||||
$priorityIndex = array_search($name, $priorityMap);
|
||||
|
||||
if ($priorityIndex !== false) {
|
||||
return $priorityIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the middleware names to look for in the priority array.
|
||||
*
|
||||
* @param string $middleware
|
||||
* @return \Generator
|
||||
*/
|
||||
protected function middlewareNames($middleware)
|
||||
{
|
||||
$stripped = head(explode(':', $middleware));
|
||||
|
||||
yield $stripped;
|
||||
|
||||
$interfaces = @class_implements($stripped);
|
||||
|
||||
if ($interfaces !== false) {
|
||||
foreach ($interfaces as $interface) {
|
||||
yield $interface;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,22 +2,27 @@
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use BackedEnum;
|
||||
use Closure;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
use Illuminate\Contracts\Routing\UrlGenerator as UrlGeneratorContract;
|
||||
use Illuminate\Contracts\Routing\UrlRoutable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\InteractsWithTime;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
|
||||
class UrlGenerator implements UrlGeneratorContract
|
||||
{
|
||||
use Macroable;
|
||||
use InteractsWithTime, Macroable;
|
||||
|
||||
/**
|
||||
* The route collection.
|
||||
*
|
||||
* @var \Illuminate\Routing\RouteCollection
|
||||
* @var \Illuminate\Routing\RouteCollectionInterface
|
||||
*/
|
||||
protected $routes;
|
||||
|
||||
@@ -28,6 +33,13 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The asset root URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $assetRoot;
|
||||
|
||||
/**
|
||||
* The forced URL root.
|
||||
*
|
||||
@@ -36,7 +48,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
protected $forcedRoot;
|
||||
|
||||
/**
|
||||
* The forced schema for URLs.
|
||||
* The forced scheme for URLs.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
@@ -50,11 +62,11 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
protected $cachedRoot;
|
||||
|
||||
/**
|
||||
* A cached copy of the URL schema for the current request.
|
||||
* A cached copy of the URL scheme for the current request.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $cachedSchema;
|
||||
protected $cachedScheme;
|
||||
|
||||
/**
|
||||
* The root namespace being applied to controller actions.
|
||||
@@ -70,6 +82,13 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
*/
|
||||
protected $sessionResolver;
|
||||
|
||||
/**
|
||||
* The encryption key resolver callable.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
protected $keyResolver;
|
||||
|
||||
/**
|
||||
* The callback to use to format hosts.
|
||||
*
|
||||
@@ -87,20 +106,22 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
/**
|
||||
* The route URL generator instance.
|
||||
*
|
||||
* @var \Illuminate\Routing\RouteUrlGenerator
|
||||
* @var \Illuminate\Routing\RouteUrlGenerator|null
|
||||
*/
|
||||
protected $routeGenerator;
|
||||
|
||||
/**
|
||||
* Create a new URL Generator instance.
|
||||
*
|
||||
* @param \Illuminate\Routing\RouteCollection $routes
|
||||
* @param \Illuminate\Routing\RouteCollectionInterface $routes
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string|null $assetRoot
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(RouteCollection $routes, Request $request)
|
||||
public function __construct(RouteCollectionInterface $routes, Request $request, $assetRoot = null)
|
||||
{
|
||||
$this->routes = $routes;
|
||||
$this->assetRoot = $assetRoot;
|
||||
|
||||
$this->setRequest($request);
|
||||
}
|
||||
@@ -141,9 +162,22 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
return $url;
|
||||
} elseif ($fallback) {
|
||||
return $this->to($fallback);
|
||||
} else {
|
||||
return $this->to('/');
|
||||
}
|
||||
|
||||
return $this->to('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the previous path info for the request.
|
||||
*
|
||||
* @param mixed $fallback
|
||||
* @return string
|
||||
*/
|
||||
public function previousPath($fallback = false)
|
||||
{
|
||||
$previousPath = str_replace($this->to('/'), '', rtrim(preg_replace('/\?.*/', '', $this->previous($fallback)), '/'));
|
||||
|
||||
return $previousPath === '' ? '/' : $previousPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,7 +218,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
// for passing the array of parameters to this URL as a list of segments.
|
||||
$root = $this->formatRoot($this->formatScheme($secure));
|
||||
|
||||
list($path, $query) = $this->extractQueryString($path);
|
||||
[$path, $query] = $this->extractQueryString($path);
|
||||
|
||||
return $this->format(
|
||||
$root, '/'.trim($path.'/'.$tail, '/')
|
||||
@@ -195,7 +229,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
* Generate a secure, absolute URL to the given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @param array $parameters
|
||||
* @param array $parameters
|
||||
* @return string
|
||||
*/
|
||||
public function secure($path, $parameters = [])
|
||||
@@ -219,7 +253,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
// Once we get the root URL, we will check to see if it contains an index.php
|
||||
// file in the paths. If it does, we will remove it since it is not needed
|
||||
// for asset paths, but only for routes to endpoints in the application.
|
||||
$root = $this->formatRoot($this->formatScheme($secure));
|
||||
$root = $this->assetRoot ?: $this->formatRoot($this->formatScheme($secure));
|
||||
|
||||
return $this->removeIndex($root).'/'.trim($path, '/');
|
||||
}
|
||||
@@ -263,7 +297,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
{
|
||||
$i = 'index.php';
|
||||
|
||||
return Str::contains($root, $i) ? str_replace('/'.$i, '', $root) : $root;
|
||||
return str_contains($root, $i) ? str_replace('/'.$i, '', $root) : $root;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,28 +306,157 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
* @param bool|null $secure
|
||||
* @return string
|
||||
*/
|
||||
public function formatScheme($secure)
|
||||
public function formatScheme($secure = null)
|
||||
{
|
||||
if (! is_null($secure)) {
|
||||
return $secure ? 'https://' : 'http://';
|
||||
}
|
||||
|
||||
if (is_null($this->cachedSchema)) {
|
||||
$this->cachedSchema = $this->forceScheme ?: $this->request->getScheme().'://';
|
||||
if (is_null($this->cachedScheme)) {
|
||||
$this->cachedScheme = $this->forceScheme ?: $this->request->getScheme().'://';
|
||||
}
|
||||
|
||||
return $this->cachedSchema;
|
||||
return $this->cachedScheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a signed route URL for a named route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $parameters
|
||||
* @param \DateTimeInterface|\DateInterval|int|null $expiration
|
||||
* @param bool $absolute
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function signedRoute($name, $parameters = [], $expiration = null, $absolute = true)
|
||||
{
|
||||
$this->ensureSignedRouteParametersAreNotReserved(
|
||||
$parameters = Arr::wrap($parameters)
|
||||
);
|
||||
|
||||
if ($expiration) {
|
||||
$parameters = $parameters + ['expires' => $this->availableAt($expiration)];
|
||||
}
|
||||
|
||||
ksort($parameters);
|
||||
|
||||
$key = call_user_func($this->keyResolver);
|
||||
|
||||
return $this->route($name, $parameters + [
|
||||
'signature' => hash_hmac('sha256', $this->route($name, $parameters, $absolute), $key),
|
||||
], $absolute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the given signed route parameters are not reserved.
|
||||
*
|
||||
* @param mixed $parameters
|
||||
* @return void
|
||||
*/
|
||||
protected function ensureSignedRouteParametersAreNotReserved($parameters)
|
||||
{
|
||||
if (array_key_exists('signature', $parameters)) {
|
||||
throw new InvalidArgumentException(
|
||||
'"Signature" is a reserved parameter when generating signed routes. Please rename your route parameter.'
|
||||
);
|
||||
}
|
||||
|
||||
if (array_key_exists('expires', $parameters)) {
|
||||
throw new InvalidArgumentException(
|
||||
'"Expires" is a reserved parameter when generating signed routes. Please rename your route parameter.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a temporary signed route URL for a named route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \DateTimeInterface|\DateInterval|int $expiration
|
||||
* @param array $parameters
|
||||
* @param bool $absolute
|
||||
* @return string
|
||||
*/
|
||||
public function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true)
|
||||
{
|
||||
return $this->signedRoute($name, $parameters, $expiration, $absolute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given request has a valid signature.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param bool $absolute
|
||||
* @param array $ignoreQuery
|
||||
* @return bool
|
||||
*/
|
||||
public function hasValidSignature(Request $request, $absolute = true, array $ignoreQuery = [])
|
||||
{
|
||||
return $this->hasCorrectSignature($request, $absolute, $ignoreQuery)
|
||||
&& $this->signatureHasNotExpired($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given request has a valid signature for a relative URL.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param array $ignoreQuery
|
||||
* @return bool
|
||||
*/
|
||||
public function hasValidRelativeSignature(Request $request, array $ignoreQuery = [])
|
||||
{
|
||||
return $this->hasValidSignature($request, false, $ignoreQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the signature from the given request matches the URL.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param bool $absolute
|
||||
* @param array $ignoreQuery
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCorrectSignature(Request $request, $absolute = true, array $ignoreQuery = [])
|
||||
{
|
||||
$ignoreQuery[] = 'signature';
|
||||
|
||||
$url = $absolute ? $request->url() : '/'.$request->path();
|
||||
|
||||
$queryString = collect(explode('&', (string) $request->server->get('QUERY_STRING')))
|
||||
->reject(fn ($parameter) => in_array(Str::before($parameter, '='), $ignoreQuery))
|
||||
->join('&');
|
||||
|
||||
$original = rtrim($url.'?'.$queryString, '?');
|
||||
|
||||
$signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));
|
||||
|
||||
return hash_equals($signature, (string) $request->query('signature', ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the expires timestamp from the given request is not from the past.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
public function signatureHasNotExpired(Request $request)
|
||||
{
|
||||
$expires = $request->query('expires');
|
||||
|
||||
return ! ($expires && Carbon::now()->getTimestamp() > $expires);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL to a named route.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $parameters
|
||||
* @param mixed $parameters
|
||||
* @param bool $absolute
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws \Symfony\Component\Routing\Exception\RouteNotFoundException
|
||||
*/
|
||||
public function route($name, $parameters = [], $absolute = true)
|
||||
{
|
||||
@@ -301,7 +464,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
return $this->toRoute($route, $parameters, $absolute);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Route [{$name}] not defined.");
|
||||
throw new RouteNotFoundException("Route [{$name}] not defined.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,13 +472,23 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
*
|
||||
* @param \Illuminate\Routing\Route $route
|
||||
* @param mixed $parameters
|
||||
* @param bool $absolute
|
||||
* @param bool $absolute
|
||||
* @return string
|
||||
*
|
||||
* @throws \Illuminate\Routing\Exceptions\UrlGenerationException
|
||||
*/
|
||||
protected function toRoute($route, $parameters, $absolute)
|
||||
public function toRoute($route, $parameters, $absolute)
|
||||
{
|
||||
$parameters = collect(Arr::wrap($parameters))->map(function ($value, $key) use ($route) {
|
||||
$value = $value instanceof UrlRoutable && $route->bindingFieldFor($key)
|
||||
? $value->{$route->bindingFieldFor($key)}
|
||||
: $value;
|
||||
|
||||
return function_exists('enum_exists') && $value instanceof BackedEnum
|
||||
? $value->value
|
||||
: $value;
|
||||
})->all();
|
||||
|
||||
return $this->routeUrl()->to(
|
||||
$route, $this->formatParameters($parameters), $absolute
|
||||
);
|
||||
@@ -324,9 +497,9 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
/**
|
||||
* Get the URL to a controller action.
|
||||
*
|
||||
* @param string $action
|
||||
* @param mixed $parameters
|
||||
* @param bool $absolute
|
||||
* @param string|array $action
|
||||
* @param mixed $parameters
|
||||
* @param bool $absolute
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
@@ -343,12 +516,16 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
/**
|
||||
* Format the given controller action.
|
||||
*
|
||||
* @param string $action
|
||||
* @param string|array $action
|
||||
* @return string
|
||||
*/
|
||||
protected function formatAction($action)
|
||||
{
|
||||
if ($this->rootNamespace && ! (strpos($action, '\\') === 0)) {
|
||||
if (is_array($action)) {
|
||||
$action = '\\'.implode('@', $action);
|
||||
}
|
||||
|
||||
if ($this->rootNamespace && ! str_starts_with($action, '\\')) {
|
||||
return $this->rootNamespace.'\\'.$action;
|
||||
} else {
|
||||
return trim($action, '\\');
|
||||
@@ -363,7 +540,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
*/
|
||||
public function formatParameters($parameters)
|
||||
{
|
||||
$parameters = array_wrap($parameters);
|
||||
$parameters = Arr::wrap($parameters);
|
||||
|
||||
foreach ($parameters as $key => $parameter) {
|
||||
if ($parameter instanceof UrlRoutable) {
|
||||
@@ -396,7 +573,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
* Get the base URL for the request.
|
||||
*
|
||||
* @param string $scheme
|
||||
* @param string $root
|
||||
* @param string|null $root
|
||||
* @return string
|
||||
*/
|
||||
public function formatRoot($scheme, $root = null)
|
||||
@@ -409,7 +586,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
$root = $this->cachedRoot;
|
||||
}
|
||||
|
||||
$start = Str::startsWith($root, 'http://') ? 'http://' : 'https://';
|
||||
$start = str_starts_with($root, 'http://') ? 'http://' : 'https://';
|
||||
|
||||
return preg_replace('~'.$start.'~', $scheme, $root, 1);
|
||||
}
|
||||
@@ -419,18 +596,19 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
*
|
||||
* @param string $root
|
||||
* @param string $path
|
||||
* @param \Illuminate\Routing\Route|null $route
|
||||
* @return string
|
||||
*/
|
||||
public function format($root, $path)
|
||||
public function format($root, $path, $route = null)
|
||||
{
|
||||
$path = '/'.trim($path, '/');
|
||||
|
||||
if ($this->formatHostUsing) {
|
||||
$root = call_user_func($this->formatHostUsing, $root);
|
||||
$root = call_user_func($this->formatHostUsing, $root, $route);
|
||||
}
|
||||
|
||||
if ($this->formatPathUsing) {
|
||||
$path = call_user_func($this->formatPathUsing, $path);
|
||||
$path = call_user_func($this->formatPathUsing, $path, $route);
|
||||
}
|
||||
|
||||
return trim($root.$path, '/');
|
||||
@@ -444,7 +622,7 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
*/
|
||||
public function isValidUrl($path)
|
||||
{
|
||||
if (! preg_match('~^(#|//|https?://|mailto:|tel:)~', $path)) {
|
||||
if (! preg_match('~^(#|//|https?://|(mailto|tel|sms):)~', $path)) {
|
||||
return filter_var($path, FILTER_VALIDATE_URL) !== false;
|
||||
}
|
||||
|
||||
@@ -476,28 +654,38 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
$this->routeUrl()->defaults($defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default named parameters used by the URL generator.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaultParameters()
|
||||
{
|
||||
return $this->routeUrl()->defaultParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the scheme for URLs.
|
||||
*
|
||||
* @param string $schema
|
||||
* @param string|null $scheme
|
||||
* @return void
|
||||
*/
|
||||
public function forceScheme($schema)
|
||||
public function forceScheme($scheme)
|
||||
{
|
||||
$this->cachedSchema = null;
|
||||
$this->cachedScheme = null;
|
||||
|
||||
$this->forceScheme = $schema.'://';
|
||||
$this->forceScheme = $scheme ? $scheme.'://' : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the forced root URL.
|
||||
*
|
||||
* @param string $root
|
||||
* @param string|null $root
|
||||
* @return void
|
||||
*/
|
||||
public function forceRootUrl($root)
|
||||
{
|
||||
$this->forcedRoot = rtrim($root, '/');
|
||||
$this->forcedRoot = $root ? rtrim($root, '/') : null;
|
||||
|
||||
$this->cachedRoot = null;
|
||||
}
|
||||
@@ -561,17 +749,24 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
$this->request = $request;
|
||||
|
||||
$this->cachedRoot = null;
|
||||
$this->cachedSchema = null;
|
||||
$this->routeGenerator = null;
|
||||
$this->cachedScheme = null;
|
||||
|
||||
tap(optional($this->routeGenerator)->defaultParameters ?: [], function ($defaults) {
|
||||
$this->routeGenerator = null;
|
||||
|
||||
if (! empty($defaults)) {
|
||||
$this->defaults($defaults);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the route collection.
|
||||
*
|
||||
* @param \Illuminate\Routing\RouteCollection $routes
|
||||
* @param \Illuminate\Routing\RouteCollectionInterface $routes
|
||||
* @return $this
|
||||
*/
|
||||
public function setRoutes(RouteCollection $routes)
|
||||
public function setRoutes(RouteCollectionInterface $routes)
|
||||
{
|
||||
$this->routes = $routes;
|
||||
|
||||
@@ -603,6 +798,40 @@ class UrlGenerator implements UrlGeneratorContract
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the encryption key resolver.
|
||||
*
|
||||
* @param callable $keyResolver
|
||||
* @return $this
|
||||
*/
|
||||
public function setKeyResolver(callable $keyResolver)
|
||||
{
|
||||
$this->keyResolver = $keyResolver;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a new instance of the URL generator with a different encryption key resolver.
|
||||
*
|
||||
* @param callable $keyResolver
|
||||
* @return \Illuminate\Routing\UrlGenerator
|
||||
*/
|
||||
public function withKeyResolver(callable $keyResolver)
|
||||
{
|
||||
return (clone $this)->setKeyResolver($keyResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root controller namespace.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRootControllerNamespace()
|
||||
{
|
||||
return $this->rootNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root controller namespace.
|
||||
*
|
||||
|
||||
60
vendor/laravel/framework/src/Illuminate/Routing/ViewController.php
vendored
Normal file
60
vendor/laravel/framework/src/Illuminate/Routing/ViewController.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Illuminate\Routing;
|
||||
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
|
||||
class ViewController extends Controller
|
||||
{
|
||||
/**
|
||||
* The response factory implementation.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Routing\ResponseFactory
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Routing\ResponseFactory $response
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ResponseFactory $response)
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the controller method.
|
||||
*
|
||||
* @param array $args
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function __invoke(...$args)
|
||||
{
|
||||
$routeParameters = array_filter($args, function ($key) {
|
||||
return ! in_array($key, ['view', 'data', 'status', 'headers']);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
$args['data'] = array_merge($args['data'], $routeParameters);
|
||||
|
||||
return $this->response->view(
|
||||
$args['view'],
|
||||
$args['data'],
|
||||
$args['status'],
|
||||
$args['headers']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an action on the controller.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function callAction($method, $parameters)
|
||||
{
|
||||
return $this->{$method}(...$parameters);
|
||||
}
|
||||
}
|
||||
@@ -14,17 +14,19 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6.4",
|
||||
"illuminate/container": "5.4.*",
|
||||
"illuminate/contracts": "5.4.*",
|
||||
"illuminate/http": "5.4.*",
|
||||
"illuminate/pipeline": "5.4.*",
|
||||
"illuminate/session": "5.4.*",
|
||||
"illuminate/support": "5.4.*",
|
||||
"symfony/debug": "~3.2",
|
||||
"symfony/http-foundation": "~3.2",
|
||||
"symfony/http-kernel": "~3.2",
|
||||
"symfony/routing": "~3.2"
|
||||
"php": "^8.0.2",
|
||||
"ext-json": "*",
|
||||
"illuminate/collections": "^9.0",
|
||||
"illuminate/container": "^9.0",
|
||||
"illuminate/contracts": "^9.0",
|
||||
"illuminate/http": "^9.0",
|
||||
"illuminate/macroable": "^9.0",
|
||||
"illuminate/pipeline": "^9.0",
|
||||
"illuminate/session": "^9.0",
|
||||
"illuminate/support": "^9.0",
|
||||
"symfony/http-foundation": "^6.0",
|
||||
"symfony/http-kernel": "^6.0",
|
||||
"symfony/routing": "^6.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -33,12 +35,13 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
"dev-master": "9.x-dev"
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"illuminate/console": "Required to use the make commands (5.4.*).",
|
||||
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)."
|
||||
"illuminate/console": "Required to use the make commands (^9.0).",
|
||||
"nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).",
|
||||
"symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)."
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
|
||||
Reference in New Issue
Block a user