1
0
mirror of https://github.com/flarum/core.git synced 2025-07-26 11:10:41 +02:00

Revamp routing

All routes are now stored in a RouteCollection, which is then used
for dispatching by the (reusable) RouterMiddleware.

This change also entails moving all routes to the service providers.
This may be changed again later, and is done for convenience reasons
right now.
This commit is contained in:
Franz Liedke
2015-06-17 00:16:35 +02:00
parent e6b9c4765a
commit b559a32f9e
12 changed files with 542 additions and 359 deletions

View File

@@ -0,0 +1,83 @@
<?php
namespace Flarum\Http;
use FastRoute\DataGenerator;
use FastRoute\RouteParser;
class RouteCollection
{
/**
* @var array
*/
protected $reverse = [];
/**
* @var DataGenerator
*/
protected $dataGenerator;
/**
* @var RouteParser
*/
protected $routeParser;
public function __construct()
{
$this->dataGenerator = new DataGenerator\GroupCountBased;
$this->routeParser = new RouteParser\Std;
}
public function get($path, $name, $handler)
{
return $this->addRoute('GET', $path, $name, $handler);
}
public function post($path, $name, $handler)
{
return $this->addRoute('POST', $path, $name, $handler);
}
public function put($path, $name, $handler)
{
return $this->addRoute('PUT', $path, $name, $handler);
}
public function delete($path, $name, $handler)
{
return $this->addRoute('DELETE', $path, $name, $handler);
}
public function addRoute($method, $path, $name, $handler)
{
$this->dataGenerator->addRoute(
$method,
$parsed = $this->routeParser->parse($path),
$handler
);
$this->reverse[$name] = $parsed;
return $this;
}
public function getRouteData()
{
return $this->dataGenerator->getData();
}
public function getPath($name, $parameters = [])
{
$parts = $this->reverse[$name];
$path = implode('', array_map(function ($part) use ($parameters) {
if (is_array($part)) {
$part = $parameters[$part[0]];
}
return $part;
}, $parts));
$path = '/' . ltrim($path, '/');
return $path;
}
}

View File

@@ -0,0 +1,9 @@
<?php
namespace Flarum\Http;
use Exception;
class RouteNotFoundException extends Exception
{
}

View File

@@ -1,137 +0,0 @@
<?php
namespace Flarum\Http;
use FastRoute\Dispatcher;
use FastRoute\RouteParser;
use FastRoute\DataGenerator;
use Psr\Http\Message\ServerRequestInterface as Request;
class Router
{
/**
* @var \FastRoute\DataGenerator
*/
protected $dataGenerator;
/**
* @var \FastRoute\RouteParser
*/
protected $routeParser;
/**
* @var string
*/
protected $currentRequestName;
/**
* @var array
*/
protected $currentRequestParameters;
/**
* @var array
*/
protected $reverse = [];
/**
* @var \FastRoute\Dispatcher
*/
protected $dispatcher;
public function __construct()
{
$this->routeParser = new RouteParser\Std;
$this->dataGenerator = new DataGenerator\GroupCountBased;
}
public function get($path, $name, $handler)
{
return $this->addRoute('GET', $path, $name, $handler);
}
public function post($path, $name, $handler)
{
return $this->addRoute('POST', $path, $name, $handler);
}
public function put($path, $name, $handler)
{
return $this->addRoute('PUT', $path, $name, $handler);
}
public function delete($path, $name, $handler)
{
return $this->addRoute('DELETE', $path, $name, $handler);
}
public function addRoute($method, $path, $name, $handler)
{
$routeData = $this->routeParser->parse($path);
$this->dataGenerator->addRoute($method, $routeData, $handler);
$routeData['method'] = $method;
$this->reverse[$name] = $routeData;
return $this;
}
public function getPath($name, $parameters = [])
{
$parts = $this->reverse[$name];
array_forget($parts, 'method');
$path = implode('', array_map(function ($part) use ($parameters) {
if (is_array($part)) {
$part = $parameters[$part[0]];
}
return $part;
}, $parts));
$path = '/' . ltrim($path, '/');
return $path;
}
public function getCurrentPath()
{
$name = $this->currentRequestName;
$parameters = $this->currentRequestParameters;
return $this->getPath($name, $parameters);
}
public function getMethod($handler)
{
return array_get($this->reverse, $handler . '.method', '');
}
public function dispatch(Request $request)
{
$method = $request->getMethod();
$uri = $request->getUri()->getPath();
$routeInfo = $this->getDispatcher()->dispatch($method, $uri);
switch ($routeInfo[0]) {
case Dispatcher::NOT_FOUND:
throw new \Exception('404 Not Found');
case Dispatcher::METHOD_NOT_ALLOWED:
throw new \Exception('405 Method Not Allowed');
case Dispatcher::FOUND:
$handler = $routeInfo[1];
$parameters = $routeInfo[2];
return $handler($request, $parameters);
}
}
protected function getDispatcher()
{
if (! isset($this->dispatcher)) {
$this->dispatcher = new Dispatcher\GroupCountBased($this->dataGenerator->getData());
}
return $this->dispatcher;
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace Flarum\Http;
use FastRoute\Dispatcher;
use FastRoute\RouteParser;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
class RouterMiddleware
{
/**
* @var RouteCollection
*/
protected $routes;
/**
* @var Dispatcher
*/
protected $dispatcher;
/**
* Create the middleware instance.
*
* @param RouteCollection $routes
*/
public function __construct(RouteCollection $routes)
{
$this->routes = $routes;
}
/**
* Dispatch the given request to our route collection.
*
* @param Request $request
* @param Response $response
* @param callable $out
* @return Response
* @throws RouteNotFoundException
*/
public function __invoke(Request $request, Response $response, callable $out = null)
{
$method = $request->getMethod();
$uri = $request->getUri()->getPath();
$routeInfo = $this->getDispatcher()->dispatch($method, $uri);dd($request, $this->routes, $routeInfo);
switch ($routeInfo[0]) {
case Dispatcher::NOT_FOUND:
case Dispatcher::METHOD_NOT_ALLOWED:
throw new RouteNotFoundException;
case Dispatcher::FOUND:
$handler = $routeInfo[1];
$parameters = $routeInfo[2];
return $handler($request, $parameters);
}
}
protected function getDispatcher()
{
if (! isset($this->dispatcher)) {
$this->dispatcher = new Dispatcher\GroupCountBased($this->routes->getRouteData());
}
return $this->dispatcher;
}
}

View File

@@ -4,17 +4,17 @@ namespace Flarum\Http;
class UrlGenerator implements UrlGeneratorInterface
{
protected $router;
protected $routes;
public function __construct(Router $router)
public function __construct(RouteCollection $routes)
{
$this->router = $router;
$this->routes = $routes;
}
public function toRoute($name, $parameters = [])
{
$path = $this->router->getPath($name, $parameters);
$path = $this->routes->getPath($name, $parameters);
$path = ltrim($path, '/');
// TODO: Prepend real base URL