v.0.1
This commit is contained in:
232
vendor/craft-group/phroute/src/Phroute/Dispatcher.php
vendored
Normal file
232
vendor/craft-group/phroute/src/Phroute/Dispatcher.php
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
<?php namespace Phroute\Phroute;
|
||||
|
||||
use Phroute\Phroute\Exception\HttpMethodNotAllowedException;
|
||||
use Phroute\Phroute\Exception\HttpRouteNotFoundException;
|
||||
|
||||
class Dispatcher {
|
||||
|
||||
private $staticRouteMap;
|
||||
private $variableRouteData;
|
||||
private $filters;
|
||||
private $handlerResolver;
|
||||
public $matchedRoute;
|
||||
|
||||
/**
|
||||
* Create a new route dispatcher.
|
||||
*
|
||||
* @param RouteDataInterface $data
|
||||
* @param HandlerResolverInterface $resolver
|
||||
*/
|
||||
public function __construct(RouteDataInterface $data, HandlerResolverInterface $resolver = null)
|
||||
{
|
||||
$this->staticRouteMap = $data->getStaticRoutes();
|
||||
|
||||
$this->variableRouteData = $data->getVariableRoutes();
|
||||
|
||||
$this->filters = $data->getFilters();
|
||||
|
||||
if ($resolver === null)
|
||||
{
|
||||
$this->handlerResolver = new HandlerResolver();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->handlerResolver = $resolver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a route for the given HTTP Method / URI.
|
||||
*
|
||||
* @param $httpMethod
|
||||
* @param $uri
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function dispatch($httpMethod, $uri)
|
||||
{
|
||||
list($handler, $filters, $vars) = $this->dispatchRoute($httpMethod, trim($uri, '/'));
|
||||
|
||||
list($beforeFilter, $afterFilter) = $this->parseFilters($filters);
|
||||
|
||||
if(($response = $this->dispatchFilters($beforeFilter)) !== null)
|
||||
{
|
||||
return $response;
|
||||
}
|
||||
|
||||
$resolvedHandler = $this->handlerResolver->resolve($handler);
|
||||
|
||||
$response = call_user_func_array($resolvedHandler, $vars);
|
||||
|
||||
return $this->dispatchFilters($afterFilter, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a route filter.
|
||||
*
|
||||
* @param $filters
|
||||
* @param null $response
|
||||
* @return mixed|null
|
||||
*/
|
||||
private function dispatchFilters($filters, $response = null)
|
||||
{
|
||||
while($filter = array_shift($filters))
|
||||
{
|
||||
$handler = $this->handlerResolver->resolve($filter['closure']);
|
||||
|
||||
$params = array_merge([$response], $filter['params']);
|
||||
|
||||
if(($filteredResponse = call_user_func_array($handler, $params)) !== null)
|
||||
{
|
||||
return $filteredResponse;
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise the array filters attached to the route and merge with any global filters.
|
||||
*
|
||||
* @param $filters
|
||||
* @return array
|
||||
*/
|
||||
private function parseFilters($filters)
|
||||
{
|
||||
$beforeFilter = array();
|
||||
$afterFilter = array();
|
||||
|
||||
if(isset($filters[Route::BEFORE]))
|
||||
{
|
||||
foreach ($filters[Route::BEFORE] as $filter){
|
||||
if(array_key_exists($filter['name'], $this->filters)){
|
||||
$beforeFilter[] = array_merge($filter, ['closure' => $this->filters[$filter['name']]]);
|
||||
}
|
||||
}
|
||||
//$beforeFilter = array_intersect_key($this->filters, array_flip((array) $filters[Route::BEFORE]));
|
||||
}
|
||||
|
||||
if(isset($filters[Route::AFTER]))
|
||||
{
|
||||
foreach ($filters[Route::AFTER] as $filter){
|
||||
if(array_key_exists($filter['name'], $this->filters)){
|
||||
$afterFilter[] = array_merge($filter, ['closure' => $this->filters[$filter['name']]]);
|
||||
}
|
||||
}
|
||||
//$afterFilter = array_intersect_key($this->filters, array_flip((array) $filters[Route::AFTER]));
|
||||
}
|
||||
|
||||
return array($beforeFilter, $afterFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the route dispatching. Check static routes first followed by variable routes.
|
||||
*
|
||||
* @param $httpMethod
|
||||
* @param $uri
|
||||
* @throws Exception\HttpRouteNotFoundException
|
||||
*/
|
||||
private function dispatchRoute($httpMethod, $uri)
|
||||
{
|
||||
if (isset($this->staticRouteMap[$uri]))
|
||||
{
|
||||
return $this->dispatchStaticRoute($httpMethod, $uri);
|
||||
}
|
||||
|
||||
return $this->dispatchVariableRoute($httpMethod, $uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the dispatching of static routes.
|
||||
*
|
||||
* @param $httpMethod
|
||||
* @param $uri
|
||||
* @return mixed
|
||||
* @throws Exception\HttpMethodNotAllowedException
|
||||
*/
|
||||
private function dispatchStaticRoute($httpMethod, $uri)
|
||||
{
|
||||
$routes = $this->staticRouteMap[$uri];
|
||||
|
||||
if (!isset($routes[$httpMethod]))
|
||||
{
|
||||
$httpMethod = $this->checkFallbacks($routes, $httpMethod);
|
||||
}
|
||||
|
||||
return $routes[$httpMethod];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check fallback routes: HEAD for GET requests followed by the ANY attachment.
|
||||
*
|
||||
* @param $routes
|
||||
* @param $httpMethod
|
||||
* @throws Exception\HttpMethodNotAllowedException
|
||||
*/
|
||||
private function checkFallbacks($routes, $httpMethod)
|
||||
{
|
||||
$additional = array(Route::ANY);
|
||||
|
||||
if($httpMethod === Route::HEAD)
|
||||
{
|
||||
$additional[] = Route::GET;
|
||||
}
|
||||
|
||||
foreach($additional as $method)
|
||||
{
|
||||
if(isset($routes[$method]))
|
||||
{
|
||||
return $method;
|
||||
}
|
||||
}
|
||||
|
||||
$this->matchedRoute = $routes;
|
||||
|
||||
throw new HttpMethodNotAllowedException('Allow: ' . implode(', ', array_keys($routes)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the dispatching of variable routes.
|
||||
*
|
||||
* @param $httpMethod
|
||||
* @param $uri
|
||||
* @throws Exception\HttpMethodNotAllowedException
|
||||
* @throws Exception\HttpRouteNotFoundException
|
||||
*/
|
||||
private function dispatchVariableRoute($httpMethod, $uri)
|
||||
{
|
||||
foreach ($this->variableRouteData as $data)
|
||||
{
|
||||
if (!preg_match($data['regex'], $uri, $matches))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$count = count($matches);
|
||||
|
||||
while(!isset($data['routeMap'][$count++]));
|
||||
|
||||
$routes = $data['routeMap'][$count - 1];
|
||||
|
||||
if (!isset($routes[$httpMethod]))
|
||||
{
|
||||
$httpMethod = $this->checkFallbacks($routes, $httpMethod);
|
||||
}
|
||||
|
||||
foreach (array_values($routes[$httpMethod][2]) as $i => $varName)
|
||||
{
|
||||
if(!isset($matches[$i + 1]) || $matches[$i + 1] === '')
|
||||
{
|
||||
unset($routes[$httpMethod][2][$varName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$routes[$httpMethod][2][$varName] = $matches[$i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return $routes[$httpMethod];
|
||||
}
|
||||
|
||||
throw new HttpRouteNotFoundException('Route ' . $uri . ' does not exist');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user