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

4.x - RouteCollectorProxy #2641

Merged
merged 11 commits into from
Apr 21, 2019
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
## 4.0.0 - 2019-07-03

### Added
- [#2641](https://github.com/slimphp/Slim/pull/2641) Add `RouteCollectorProxyInterface` which extracts all the route mapping functionality from app into its own interface.
- [#2640](https://github.com/slimphp/Slim/pull/2640) Add `RouteParserInterface` and decouple FastRoute route parser entirely from core. The methods `relativePathFor()`, `urlFor()` and `fullUrlFor()` are now located on this interface.
- [#2639](https://github.com/slimphp/Slim/pull/2639) Add `DispatcherInterface` and decouple FastRoute dispatcher entirely from core. This enables us to swap out our router implementation for any other router.
- [#2638](https://github.com/slimphp/Slim/pull/2638) Add `RouteCollector::fullUrlFor()` to give the ability to generate fully qualified URLs
Expand All @@ -24,6 +25,7 @@

### Deprecated

- [#2641](https://github.com/slimphp/Slim/pull/2641) Deprecate `RouteCollector::pushGroup()`,`RouteCollector::popGroup()` which gets replaced by `RouteCollector::group()`
- [#2638](https://github.com/slimphp/Slim/pull/2638) Deprecate `RouteCollector::pathFor()` which gets replaced by `RouteCollector::urlFor()` preserving the orignal functionality
- [#2555](https://github.com/slimphp/Slim/pull/2555) Double-Pass Middleware Support has been deprecated

Expand Down
266 changes: 21 additions & 245 deletions Slim/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,16 @@

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 Slim\Interfaces\CallableResolverInterface;
use Slim\Interfaces\RouteCollectorInterface;
use Slim\Interfaces\RouteGroupInterface;
use Slim\Interfaces\RouteInterface;
use Slim\Interfaces\RouteResolverInterface;
use Slim\Routing\RouteCollector;
use Slim\Routing\RouteCollectorProxy;
use Slim\Routing\RouteResolver;
use Slim\Routing\RouteRunner;

Expand All @@ -33,7 +29,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 @@ -42,50 +38,24 @@ class App implements RequestHandlerInterface
*/
public const VERSION = '4.0.0-dev';

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

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

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

/**
* @var RouteCollectorInterface
*/
protected $routeCollector;

/**
* @var RouteResolverInterface
*/
protected $routeResolver;

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

/********************************************************************************
* Constructor
*******************************************************************************/

/**
* Create new application
*
* @param ResponseFactoryInterface $responseFactory
* @param ContainerInterface|null $container
* @param CallableResolverInterface $callableResolver
* @param RouteCollectorInterface $routeCollector
* @param RouteResolverInterface $routeResolver
* @param ResponseFactoryInterface $responseFactory
* @param ContainerInterface|null $container
* @param CallableResolverInterface|null $callableResolver
* @param RouteCollectorInterface|null $routeCollector
* @param RouteResolverInterface|null $routeResolver
*/
public function __construct(
ResponseFactoryInterface $responseFactory,
Expand All @@ -94,20 +64,27 @@ public function __construct(
RouteCollectorInterface $routeCollector = null,
RouteResolverInterface $routeResolver = null
) {
$this->responseFactory = $responseFactory;
$this->container = $container;
$this->callableResolver = $callableResolver ?? new CallableResolver($container);
$this->routeCollector = $routeCollector ?? new RouteCollector(
parent::__construct(
$responseFactory,
$this->callableResolver,
$container
$callableResolver ?? new CallableResolver($container),
$container,
$routeCollector
);
$this->routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector);

$this->routeResolver = $routeResolver ?? new RouteResolver($this->routeCollector);
$routeRunner = new RouteRunner($this->routeResolver);

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

/**
* @return RouteResolverInterface
*/
public function getRouteResolver(): RouteResolverInterface
{
return $this->routeResolver;
}

/**
* @param MiddlewareInterface|string|callable $middleware
* @return self
Expand All @@ -128,207 +105,6 @@ public function addMiddleware(MiddlewareInterface $middleware): self
return $this;
}

/********************************************************************************
* Getter methods
*******************************************************************************/

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

/**
* Get callable resolver
*
* @return CallableResolverInterface
*/
public function getCallableResolver(): CallableResolverInterface
{
return $this->callableResolver;
}

/**
* Get route collector
*
* @return RouteCollectorInterface
*/
public function getRouteCollector(): RouteCollectorInterface
{
return $this->routeCollector;
}

/**
* Get route resolver
*
* @return RouteResolverInterface
*/
public function getRouteResolver(): RouteResolverInterface
{
return $this->routeResolver;
}

/********************************************************************************
* 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);
}

return $this->routeCollector->map($methods, $pattern, $callable);
}

/**
* 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
*
* @return RouteGroupInterface
*/
public function group(string $pattern, $callable): RouteGroupInterface
{
$group = $this->routeCollector->pushGroup($pattern, $callable);
$group($this);
$this->routeCollector->popGroup();
return $group;
}

/********************************************************************************
* Runner
*******************************************************************************/

/**
* Run application
*
Expand Down
18 changes: 6 additions & 12 deletions Slim/Interfaces/RouteCollectorInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ public function getNamedRoute(string $name): RouteInterface;
public function removeNamedRoute(string $name): RouteCollectorInterface;

/**
* Lookup a route via the route's unique identifier
*
* @param string $identifier
*
* @return RouteInterface
Expand All @@ -107,21 +109,13 @@ public function removeNamedRoute(string $name): RouteCollectorInterface;
public function lookupRoute(string $identifier): RouteInterface;

/**
* Add a route group to the array
*
* @param string $pattern The group pattern
* @param callable $callable A group callable
* Add route group
*
* @param string $pattern
* @param string|callable $callable
* @return RouteGroupInterface
*/
public function pushGroup(string $pattern, $callable): RouteGroupInterface;

/**
* Removes the last route group from the array
*
* @return RouteGroupInterface|null
*/
public function popGroup(): ?RouteGroupInterface;
public function group(string $pattern, $callable): RouteGroupInterface;

/**
* Add route
Expand Down
Loading