Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] 4.x Refactor Routing #2604

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 25 additions & 204 deletions Slim/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@

namespace Slim;

use Closure;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UriInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use RuntimeException;
use Slim\Interfaces\CallableResolverInterface;
use Slim\Interfaces\RouteGroupInterface;
use Slim\Interfaces\RouteInterface;
use Slim\Interfaces\RouterInterface;
use Slim\Interfaces\RouteCollectorInterface;
use Slim\Interfaces\RouteResolverInterface;
use Slim\Routing\RouteCollector;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteResolver;
use Slim\Routing\RouteRunner;

/**
* App
Expand All @@ -32,7 +32,7 @@
* configure, and run a Slim Framework application.
* The \Slim\App class also accepts Slim Framework middleware.
*/
class App implements RequestHandlerInterface
class App extends RouteCollectorProxy implements RequestHandlerInterface
{
/**
* Current version
Expand All @@ -41,32 +41,15 @@ class App implements RequestHandlerInterface
*/
const VERSION = '4.0.0-dev';

/**
* Container
*
* @var ContainerInterface|null
*/
private $container;

/**
* @var CallableResolverInterface
*/
protected $callableResolver;

/**
* @var MiddlewareDispatcher
*/
protected $middlewareDispatcher;

/**
* @var RouterInterface
*/
protected $router;

/**
* @var ResponseFactoryInterface
* @var RouteResolver
*/
protected $responseFactory;
protected $routeResolver;

/********************************************************************************
* Constructor
Expand All @@ -78,19 +61,24 @@ class App implements RequestHandlerInterface
* @param ResponseFactoryInterface $responseFactory
* @param ContainerInterface|null $container
* @param CallableResolverInterface $callableResolver
* @param RouterInterface $router
* @param RouteCollectorInterface $routeCollector
* @param RouteResolverInterface $routeResolver
*/
public function __construct(
ResponseFactoryInterface $responseFactory,
ContainerInterface $container = null,
CallableResolverInterface $callableResolver = null,
RouterInterface $router = null
RouteCollectorInterface $routeCollector = null,
RouteResolverInterface $routeResolver = null
) {
$this->responseFactory = $responseFactory;
$this->container = $container;
$this->callableResolver = $callableResolver ?? new CallableResolver($container);
$this->router = $router ?? new Router($responseFactory, $this->callableResolver, $this->container);
$this->middlewareDispatcher = new MiddlewareDispatcher(new RouteDispatcher($this->router), $container);
$callableResolver = $callableResolver ?? new CallableResolver($container);
$routeCollector = $routeCollector ?? new RouteCollector($responseFactory, $callableResolver, $container);
$routeResolver = $routeResolver ?? new RouteResolver($routeCollector);

$routeRunner = new RouteRunner($routeResolver);
$this->middlewareDispatcher = new MiddlewareDispatcher($routeRunner, $container);

parent::__construct($responseFactory, $callableResolver, $routeCollector, $container);
}

/**
Expand All @@ -117,16 +105,6 @@ public function addMiddleware(MiddlewareInterface $middleware): self
* Getter methods
*******************************************************************************/

/**
* Get container
*
* @return ContainerInterface|null
*/
public function getContainer(): ?ContainerInterface
{
return $this->container;
}

/**
* Get callable resolver
*
Expand All @@ -138,170 +116,13 @@ public function getCallableResolver(): CallableResolverInterface
}

/**
* Get router
*
* @return RouterInterface
*/
public function getRouter(): RouterInterface
{
return $this->router;
}

/********************************************************************************
* Router proxy methods
*******************************************************************************/

/**
* Add GET route
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function get(string $pattern, $callable): RouteInterface
{
return $this->map(['GET'], $pattern, $callable);
}

/**
* Add POST route
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function post(string $pattern, $callable): RouteInterface
{
return $this->map(['POST'], $pattern, $callable);
}

/**
* Add PUT route
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function put(string $pattern, $callable): RouteInterface
{
return $this->map(['PUT'], $pattern, $callable);
}

/**
* Add PATCH route
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function patch(string $pattern, $callable): RouteInterface
{
return $this->map(['PATCH'], $pattern, $callable);
}

/**
* Add DELETE route
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function delete(string $pattern, $callable): RouteInterface
{
return $this->map(['DELETE'], $pattern, $callable);
}

/**
* Add OPTIONS route
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function options(string $pattern, $callable): RouteInterface
{
return $this->map(['OPTIONS'], $pattern, $callable);
}

/**
* Add route for any HTTP method
*
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function any(string $pattern, $callable): RouteInterface
{
return $this->map(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], $pattern, $callable);
}

/**
* Add route with multiple methods
*
* @param string[] $methods Numeric array of HTTP method names
* @param string $pattern The route URI pattern
* @param callable|string $callable The route callback routine
*
* @return RouteInterface
*/
public function map(array $methods, string $pattern, $callable): RouteInterface
{
// Bind route callable to container, if present
if ($this->container instanceof ContainerInterface && $callable instanceof \Closure) {
$callable = $callable->bindTo($this->container);
}

/** @var Router $router */
$router = $this->getRouter();
$route = $router->map($methods, $pattern, $callable);

return $route;
}

/**
* Add a route that sends an HTTP redirect
*
* @param string $from
* @param string|UriInterface $to
* @param int $status
*
* @return RouteInterface
*/
public function redirect(string $from, $to, int $status = 302): RouteInterface
{
$handler = function () use ($to, $status) {
$response = $this->responseFactory->createResponse($status);
return $response->withHeader('Location', (string)$to);
};

return $this->get($from, $handler);
}

/**
* Route Groups
*
* This method accepts a route pattern and a callback. All route
* declarations in the callback will be prepended by the group(s)
* that it is in.
*
* @param string $pattern
* @param callable $callable
* Get route collector
*
* @return RouteGroupInterface
* @return RouteCollectorInterface
*/
public function group(string $pattern, $callable): RouteGroupInterface
public function getRouteCollector(): RouteCollectorInterface
{
$group = $this->router->pushGroup($pattern, $callable);
$group($this);
$this->router->popGroup();
return $group;
return $this->routeCollector;
}

/********************************************************************************
Expand Down
Loading