Added nikic/fast-route as routing dispatcher
This commit is contained in:
parent
73c9d923e7
commit
a1bc763a16
|
@ -22,6 +22,7 @@
|
||||||
"illuminate/container": "5.5.*",
|
"illuminate/container": "5.5.*",
|
||||||
"illuminate/database": "5.5.*",
|
"illuminate/database": "5.5.*",
|
||||||
"illuminate/support": "^5.5",
|
"illuminate/support": "^5.5",
|
||||||
|
"nikic/fast-route": "^1.3",
|
||||||
"psr/container": "^1.0",
|
"psr/container": "^1.0",
|
||||||
"psr/http-server-middleware": "^1.0",
|
"psr/http-server-middleware": "^1.0",
|
||||||
"psr/log": "^1.0",
|
"psr/log": "^1.0",
|
||||||
|
|
|
@ -15,13 +15,15 @@ return [
|
||||||
\Engelsystem\Http\SessionServiceProvider::class,
|
\Engelsystem\Http\SessionServiceProvider::class,
|
||||||
\Engelsystem\Http\ResponseServiceProvider::class,
|
\Engelsystem\Http\ResponseServiceProvider::class,
|
||||||
\Engelsystem\Http\Psr7ServiceProvider::class,
|
\Engelsystem\Http\Psr7ServiceProvider::class,
|
||||||
|
\Engelsystem\Middleware\RouteDispatcherServiceProvider::class,
|
||||||
|
\Engelsystem\Middleware\RequestHandlerServiceProvider::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
// Application middleware
|
// Application middleware
|
||||||
'middleware' => [
|
'middleware' => [
|
||||||
\Engelsystem\Middleware\SendResponseHandler::class,
|
\Engelsystem\Middleware\SendResponseHandler::class,
|
||||||
\Engelsystem\Middleware\ExceptionHandler::class,
|
\Engelsystem\Middleware\ExceptionHandler::class,
|
||||||
\Engelsystem\Middleware\LegacyMiddleware::class,
|
\Engelsystem\Middleware\RouteDispatcher::class,
|
||||||
\Engelsystem\Middleware\NotFoundResponse::class,
|
\Engelsystem\Middleware\RequestHandler::class,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use FastRoute\RouteCollector;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
|
||||||
|
/** @var RouteCollector $route */
|
||||||
|
|
||||||
|
/** Demo route endpoint, TODO: Remove */
|
||||||
|
$route->addRoute('GET', '/hello/{name}', function ($request) {
|
||||||
|
/** @var ServerRequestInterface $request */
|
||||||
|
$name = $request->getAttribute('name');
|
||||||
|
|
||||||
|
return response(sprintf('Hello %s!', htmlspecialchars($name)));
|
||||||
|
});
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Container\Container;
|
||||||
|
use Engelsystem\Http\Response;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class CallableHandler implements MiddlewareInterface, RequestHandlerInterface
|
||||||
|
{
|
||||||
|
/** @var callable */
|
||||||
|
protected $callable;
|
||||||
|
|
||||||
|
/** @var Container */
|
||||||
|
protected $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param callable $callable The callable that should be wrapped
|
||||||
|
* @param Container $container
|
||||||
|
*/
|
||||||
|
public function __construct(callable $callable, Container $container = null)
|
||||||
|
{
|
||||||
|
$this->callable = $callable;
|
||||||
|
$this->container = $container;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
|
* response creation to a handler.
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @param RequestHandlerInterface $handler
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->execute([$request, $handler]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the request and return a response.
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->execute([$request]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the callable and return a response
|
||||||
|
*
|
||||||
|
* @param array $arguments
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
protected function execute(array $arguments = []): ResponseInterface
|
||||||
|
{
|
||||||
|
$return = call_user_func_array($this->callable, $arguments);
|
||||||
|
|
||||||
|
if ($return instanceof ResponseInterface) {
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->container instanceof Container) {
|
||||||
|
throw new InvalidArgumentException('Unable to resolve response');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Response $response */
|
||||||
|
$response = $this->container->get('response');
|
||||||
|
return $response->withContent($return);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,8 @@ use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
|
class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
|
||||||
{
|
{
|
||||||
|
use ResolvesMiddlewareTrait;
|
||||||
|
|
||||||
/** @var MiddlewareInterface[]|string[] */
|
/** @var MiddlewareInterface[]|string[] */
|
||||||
protected $stack;
|
protected $stack;
|
||||||
|
|
||||||
|
@ -70,10 +72,7 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
|
||||||
throw new LogicException('Middleware queue is empty');
|
throw new LogicException('Middleware queue is empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($middleware)) {
|
|
||||||
$middleware = $this->resolveMiddleware($middleware);
|
$middleware = $this->resolveMiddleware($middleware);
|
||||||
}
|
|
||||||
|
|
||||||
if (!$middleware instanceof MiddlewareInterface) {
|
if (!$middleware instanceof MiddlewareInterface) {
|
||||||
throw new InvalidArgumentException('Middleware is no instance of ' . MiddlewareInterface::class);
|
throw new InvalidArgumentException('Middleware is no instance of ' . MiddlewareInterface::class);
|
||||||
}
|
}
|
||||||
|
@ -81,25 +80,6 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface
|
||||||
return $middleware->process($request, $this);
|
return $middleware->process($request, $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve the middleware with the container
|
|
||||||
*
|
|
||||||
* @param string $middleware
|
|
||||||
* @return MiddlewareInterface
|
|
||||||
*/
|
|
||||||
protected function resolveMiddleware($middleware)
|
|
||||||
{
|
|
||||||
if (!$this->container instanceof Application) {
|
|
||||||
throw new InvalidArgumentException('Unable to resolve middleware ' . $middleware);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->container->has($middleware)) {
|
|
||||||
return $this->container->get($middleware);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->container->make($middleware);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Application $container
|
* @param Application $container
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -83,7 +83,9 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($title) and empty($content)) {
|
if (empty($title) and empty($content)) {
|
||||||
return $handler->handle($request);
|
$page = '404';
|
||||||
|
$title = _('Page not found');
|
||||||
|
$content = _('This page could not be found or you don\'t have permission to view it. You probably have to sign in or register in order to gain access!');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->renderPage($page, $title, $content);
|
return $this->renderPage($page, $title, $content);
|
||||||
|
@ -270,10 +272,17 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
$parameters = [
|
$parameters = [
|
||||||
'key' => (isset($user) ? $user['api_key'] : ''),
|
'key' => (isset($user) ? $user['api_key'] : ''),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($page == 'user_meetings') {
|
if ($page == 'user_meetings') {
|
||||||
$parameters['meetings'] = 1;
|
$parameters['meetings'] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$status = 200;
|
||||||
|
if ($page == '404') {
|
||||||
|
$status = 404;
|
||||||
|
$content = info($content, true);
|
||||||
|
}
|
||||||
|
|
||||||
return response(view(__DIR__ . '/../../templates/layout.html', [
|
return response(view(__DIR__ . '/../../templates/layout.html', [
|
||||||
'theme' => isset($user) ? $user['color'] : config('theme'),
|
'theme' => isset($user) ? $user['color'] : config('theme'),
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
|
@ -291,6 +300,6 @@ class LegacyMiddleware implements MiddlewareInterface
|
||||||
'contact_email' => config('contact_email'),
|
'contact_email' => config('contact_email'),
|
||||||
'locale' => locale(),
|
'locale' => locale(),
|
||||||
'event_info' => EventConfig_info($event_config) . ' <br />'
|
'event_info' => EventConfig_info($event_config) . ' <br />'
|
||||||
]));
|
]), $status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Engelsystem\Middleware;
|
|
||||||
|
|
||||||
use Engelsystem\Http\Response;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Psr\Http\Server\MiddlewareInterface;
|
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
|
||||||
|
|
||||||
class NotFoundResponse implements MiddlewareInterface
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns a 404: Page not found response
|
|
||||||
*
|
|
||||||
* Should be the last middleware
|
|
||||||
*
|
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
* @param RequestHandlerInterface $handler
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function process(
|
|
||||||
ServerRequestInterface $request,
|
|
||||||
RequestHandlerInterface $handler
|
|
||||||
): ResponseInterface {
|
|
||||||
$info = _('This page could not be found or you don\'t have permission to view it. You probably have to sign in or register in order to gain access!');
|
|
||||||
|
|
||||||
return $this->renderPage($info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $content
|
|
||||||
* @return Response
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
protected function renderPage($content)
|
|
||||||
{
|
|
||||||
global $user;
|
|
||||||
$event_config = EventConfig();
|
|
||||||
|
|
||||||
return response(view(__DIR__ . '/../../templates/layout.html', [
|
|
||||||
'theme' => isset($user) ? $user['color'] : config('theme'),
|
|
||||||
'title' => _('Page not found'),
|
|
||||||
'atom_link' => '',
|
|
||||||
'start_page_url' => page_link_to('/'),
|
|
||||||
'credits_url' => page_link_to('credits'),
|
|
||||||
'menu' => make_menu(),
|
|
||||||
'content' => msg() . info($content),
|
|
||||||
'header_toolbar' => header_toolbar(),
|
|
||||||
'faq_url' => config('faq_url'),
|
|
||||||
'contact_email' => config('contact_email'),
|
|
||||||
'locale' => locale(),
|
|
||||||
'event_info' => EventConfig_info($event_config) . ' <br />'
|
|
||||||
]), 404);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Application;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class RequestHandler implements MiddlewareInterface
|
||||||
|
{
|
||||||
|
use ResolvesMiddlewareTrait;
|
||||||
|
|
||||||
|
/** @var Application */
|
||||||
|
protected $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Application $container
|
||||||
|
*/
|
||||||
|
public function __construct(Application $container)
|
||||||
|
{
|
||||||
|
$this->container = $container;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
|
* response creation to a handler.
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @param RequestHandlerInterface $handler
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
$requestHandler = $request->getAttribute('route-request-handler');
|
||||||
|
$requestHandler = $this->resolveMiddleware($requestHandler);
|
||||||
|
|
||||||
|
if ($requestHandler instanceof MiddlewareInterface) {
|
||||||
|
return $requestHandler->process($request, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($requestHandler instanceof RequestHandlerInterface) {
|
||||||
|
return $requestHandler->handle($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidArgumentException('Unable to process request handler of type ' . gettype($requestHandler));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Container\ServiceProvider;
|
||||||
|
|
||||||
|
class RequestHandlerServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
/** @var RequestHandler $requestHandler */
|
||||||
|
$requestHandler = $this->app->make(RequestHandler::class);
|
||||||
|
|
||||||
|
$this->app->instance('request.handler', $requestHandler);
|
||||||
|
$this->app->bind(RequestHandler::class, 'request.handler');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Application;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
trait ResolvesMiddlewareTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Resolve the middleware with the container
|
||||||
|
*
|
||||||
|
* @param string|callable|MiddlewareInterface|RequestHandlerInterface $middleware
|
||||||
|
* @return MiddlewareInterface|RequestHandlerInterface
|
||||||
|
*/
|
||||||
|
protected function resolveMiddleware($middleware)
|
||||||
|
{
|
||||||
|
if ($this->isMiddleware($middleware)) {
|
||||||
|
return $middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!property_exists($this, 'container') || !$this->container instanceof Application) {
|
||||||
|
throw new InvalidArgumentException('Unable to resolve middleware');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var Application $container */
|
||||||
|
$container = $this->container;
|
||||||
|
|
||||||
|
if (is_string($middleware)) {
|
||||||
|
$middleware = $container->make($middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_callable($middleware)) {
|
||||||
|
$middleware = $container->make(CallableHandler::class, ['callable' => $middleware]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->isMiddleware($middleware)) {
|
||||||
|
return $middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidArgumentException('Unable to resolve middleware');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given object is a middleware or middleware or request handler
|
||||||
|
*
|
||||||
|
* @param mixed $middleware
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isMiddleware($middleware)
|
||||||
|
{
|
||||||
|
return ($middleware instanceof MiddlewareInterface || $middleware instanceof RequestHandlerInterface);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Middleware;
|
||||||
|
|
||||||
|
use FastRoute\Dispatcher as FastRouteDispatcher;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class RouteDispatcher implements MiddlewareInterface
|
||||||
|
{
|
||||||
|
/** @var FastRouteDispatcher */
|
||||||
|
protected $dispatcher;
|
||||||
|
|
||||||
|
/** @var ResponseInterface */
|
||||||
|
protected $response;
|
||||||
|
|
||||||
|
/** @var MiddlewareInterface|null */
|
||||||
|
protected $notFound;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param FastRouteDispatcher $dispatcher
|
||||||
|
* @param ResponseInterface $response Default response
|
||||||
|
* @param MiddlewareInterface|null $notFound Handles any requests if the route can't be found
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
FastRouteDispatcher $dispatcher,
|
||||||
|
ResponseInterface $response,
|
||||||
|
MiddlewareInterface $notFound = null
|
||||||
|
) {
|
||||||
|
$this->dispatcher = $dispatcher;
|
||||||
|
$this->response = $response;
|
||||||
|
$this->notFound = $notFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process an incoming server request and return a response, optionally delegating
|
||||||
|
* response creation to a handler.
|
||||||
|
*
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @param RequestHandlerInterface $handler
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
$route = $this->dispatcher->dispatch($request->getMethod(), urldecode($request->getUri()->getPath()));
|
||||||
|
|
||||||
|
$status = $route[0];
|
||||||
|
if ($status == FastRouteDispatcher::NOT_FOUND) {
|
||||||
|
if ($this->notFound instanceof MiddlewareInterface) {
|
||||||
|
return $this->notFound->process($request, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->response->withStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($status == FastRouteDispatcher::METHOD_NOT_ALLOWED) {
|
||||||
|
$methods = $route[1];
|
||||||
|
return $this->response
|
||||||
|
->withStatus(405)
|
||||||
|
->withHeader('Allow', implode(', ', $methods));
|
||||||
|
}
|
||||||
|
|
||||||
|
$routeHandler = $route[1];
|
||||||
|
$request = $request->withAttribute('route-request-handler', $routeHandler);
|
||||||
|
|
||||||
|
$vars = $route[2];
|
||||||
|
foreach ($vars as $name => $value) {
|
||||||
|
$request = $request->withAttribute($name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $handler->handle($request);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Container\ServiceProvider;
|
||||||
|
use FastRoute\Dispatcher as FastRouteDispatcher;
|
||||||
|
use FastRoute\RouteCollector;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
|
||||||
|
class RouteDispatcherServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->alias(RouteDispatcher::class, 'route.dispatcher');
|
||||||
|
|
||||||
|
$this->app
|
||||||
|
->when(RouteDispatcher::class)
|
||||||
|
->needs(FastRouteDispatcher::class)
|
||||||
|
->give(function () {
|
||||||
|
return $this->generateRouting();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->app
|
||||||
|
->when(RouteDispatcher::class)
|
||||||
|
->needs(MiddlewareInterface::class)
|
||||||
|
->give(LegacyMiddleware::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes the routes.php file
|
||||||
|
*
|
||||||
|
* @return FastRouteDispatcher
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
function generateRouting()
|
||||||
|
{
|
||||||
|
return \FastRoute\simpleDispatcher(function (RouteCollector $route) {
|
||||||
|
require config_path('routes.php');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Container\Container;
|
||||||
|
use Engelsystem\Http\Response;
|
||||||
|
use Engelsystem\Middleware\CallableHandler;
|
||||||
|
use Engelsystem\Test\Unit\Middleware\Stub\HasStaticMethod;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use ReflectionClass as Reflection;
|
||||||
|
use stdClass;
|
||||||
|
|
||||||
|
class CallableHandlerTest extends TestCase
|
||||||
|
{
|
||||||
|
public function provideCallable()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[function () { }],
|
||||||
|
[[$this, 'provideCallable']],
|
||||||
|
[[HasStaticMethod::class, 'foo']],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideCallable
|
||||||
|
* @covers \Engelsystem\Middleware\CallableHandler::__construct
|
||||||
|
* @param callable $callable
|
||||||
|
*/
|
||||||
|
public function testInit($callable)
|
||||||
|
{
|
||||||
|
$handler = new CallableHandler($callable);
|
||||||
|
|
||||||
|
$reflection = new Reflection(get_class($handler));
|
||||||
|
$property = $reflection->getProperty('callable');
|
||||||
|
$property->setAccessible(true);
|
||||||
|
|
||||||
|
$this->assertEquals($callable, $property->getValue($handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\CallableHandler::process
|
||||||
|
*/
|
||||||
|
public function testProcess()
|
||||||
|
{
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
/** @var callable|MockObject $callable */
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
list($request, $response, $callable, $handler) = $this->getMocks();
|
||||||
|
|
||||||
|
$callable->expects($this->once())
|
||||||
|
->method('__invoke')
|
||||||
|
->with($request, $handler)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$middleware = new CallableHandler($callable);
|
||||||
|
$middleware->process($request, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\CallableHandler::handle
|
||||||
|
*/
|
||||||
|
public function testHandler()
|
||||||
|
{
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
/** @var callable|MockObject $callable */
|
||||||
|
list($request, $response, $callable) = $this->getMocks();
|
||||||
|
|
||||||
|
$callable->expects($this->once())
|
||||||
|
->method('__invoke')
|
||||||
|
->with($request)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$middleware = new CallableHandler($callable);
|
||||||
|
$middleware->handle($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\CallableHandler::execute
|
||||||
|
*/
|
||||||
|
public function testExecute()
|
||||||
|
{
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
/** @var Response|MockObject $response */
|
||||||
|
/** @var callable|MockObject $callable */
|
||||||
|
list($request, $response, $callable) = $this->getMocks();
|
||||||
|
/** @var Container|MockObject $container */
|
||||||
|
$container = $this->createMock(Container::class);
|
||||||
|
|
||||||
|
$callable->expects($this->exactly(3))
|
||||||
|
->method('__invoke')
|
||||||
|
->with($request)
|
||||||
|
->willReturnOnConsecutiveCalls($response, 'Lorem ipsum?', 'I\'m not an exception!');
|
||||||
|
|
||||||
|
$container->expects($this->once())
|
||||||
|
->method('get')
|
||||||
|
->with('response')
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$response->expects($this->once())
|
||||||
|
->method('withContent')
|
||||||
|
->with('Lorem ipsum?')
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$middleware = new CallableHandler($callable, $container);
|
||||||
|
$return = $middleware->handle($request);
|
||||||
|
$this->assertInstanceOf(ResponseInterface::class, $return);
|
||||||
|
$this->assertEquals($response, $return);
|
||||||
|
|
||||||
|
$return = $middleware->handle($request);
|
||||||
|
$this->assertInstanceOf(ResponseInterface::class, $return);
|
||||||
|
$this->assertEquals($response, $return);
|
||||||
|
|
||||||
|
$middleware = new CallableHandler($callable);
|
||||||
|
$this->expectException(\InvalidArgumentException::class);
|
||||||
|
$middleware->handle($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getMocks(): array
|
||||||
|
{
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||||
|
/** @var Response|MockObject $response */
|
||||||
|
$response = $this->createMock(Response::class);
|
||||||
|
/** @var callable|MockObject $callable */
|
||||||
|
$callable = $this->getMockBuilder(stdClass::class)
|
||||||
|
->setMethods(['__invoke'])
|
||||||
|
->getMock();
|
||||||
|
return array($request, $response, $callable, $handler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ namespace Engelsystem\Test\Unit\Middleware;
|
||||||
use Engelsystem\Application;
|
use Engelsystem\Application;
|
||||||
use Engelsystem\Middleware\Dispatcher;
|
use Engelsystem\Middleware\Dispatcher;
|
||||||
use Engelsystem\Test\Unit\Middleware\Stub\NotARealMiddleware;
|
use Engelsystem\Test\Unit\Middleware\Stub\NotARealMiddleware;
|
||||||
use Engelsystem\Test\Unit\Middleware\Stub\ReturnResponseMiddleware;
|
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
@ -158,14 +157,14 @@ class DispatcherTest extends TestCase
|
||||||
|
|
||||||
/** @var Dispatcher|MockObject $dispatcher */
|
/** @var Dispatcher|MockObject $dispatcher */
|
||||||
$dispatcher = $this->getMockBuilder(Dispatcher::class)
|
$dispatcher = $this->getMockBuilder(Dispatcher::class)
|
||||||
->setConstructorArgs([[MiddlewareInterface::class]])
|
->setConstructorArgs([[MiddlewareInterface::class, MiddlewareInterface::class]])
|
||||||
->setMethods(['resolveMiddleware'])
|
->setMethods(['resolveMiddleware'])
|
||||||
->getMock();
|
->getMock();
|
||||||
|
|
||||||
$dispatcher->expects($this->once())
|
$dispatcher->expects($this->exactly(2))
|
||||||
->method('resolveMiddleware')
|
->method('resolveMiddleware')
|
||||||
->with(MiddlewareInterface::class)
|
->with(MiddlewareInterface::class)
|
||||||
->willReturn($middleware);
|
->willReturnOnConsecutiveCalls($middleware, null);
|
||||||
|
|
||||||
$middleware->expects($this->once())
|
$middleware->expects($this->once())
|
||||||
->method('process')
|
->method('process')
|
||||||
|
@ -174,57 +173,26 @@ class DispatcherTest extends TestCase
|
||||||
|
|
||||||
$return = $dispatcher->handle($request);
|
$return = $dispatcher->handle($request);
|
||||||
$this->assertEquals($response, $return);
|
$this->assertEquals($response, $return);
|
||||||
|
|
||||||
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
$dispatcher->handle($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers \Engelsystem\Middleware\Dispatcher::resolveMiddleware
|
|
||||||
* @covers \Engelsystem\Middleware\Dispatcher::setContainer
|
* @covers \Engelsystem\Middleware\Dispatcher::setContainer
|
||||||
*/
|
*/
|
||||||
public function testResolveMiddleware()
|
public function testSetContainer()
|
||||||
{
|
{
|
||||||
/** @var Application|MockObject $container */
|
/** @var Application|MockObject $container */
|
||||||
$container = $this->createMock(Application::class);
|
$container = $this->createMock(Application::class);
|
||||||
/** @var ServerRequestInterface|MockObject $request */
|
|
||||||
$request = $this->createMock(ServerRequestInterface::class);
|
|
||||||
/** @var ResponseInterface|MockObject $response */
|
|
||||||
$response = $this->createMock(ResponseInterface::class);
|
|
||||||
|
|
||||||
$returnResponseMiddleware = new ReturnResponseMiddleware($response);
|
$middleware = new Dispatcher();
|
||||||
|
$middleware->setContainer($container);
|
||||||
|
|
||||||
$container->expects($this->exactly(2))
|
$reflection = new Reflection(get_class($middleware));
|
||||||
->method('has')
|
$property = $reflection->getProperty('container');
|
||||||
->withConsecutive([ReturnResponseMiddleware::class], ['middleware'])
|
$property->setAccessible(true);
|
||||||
->willReturnOnConsecutiveCalls(false, true);
|
|
||||||
|
|
||||||
$container->expects($this->once())
|
$this->assertEquals($container, $property->getValue($middleware));
|
||||||
->method('make')
|
|
||||||
->with(ReturnResponseMiddleware::class)
|
|
||||||
->willReturn($returnResponseMiddleware);
|
|
||||||
|
|
||||||
$container->expects($this->once())
|
|
||||||
->method('get')
|
|
||||||
->with('middleware')
|
|
||||||
->willReturn($returnResponseMiddleware);
|
|
||||||
|
|
||||||
$dispatcher = new Dispatcher([ReturnResponseMiddleware::class]);
|
|
||||||
$dispatcher->setContainer($container);
|
|
||||||
$dispatcher->handle($request);
|
|
||||||
|
|
||||||
$dispatcher = new Dispatcher(['middleware'], $container);
|
|
||||||
$dispatcher->handle($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @covers \Engelsystem\Middleware\Dispatcher::resolveMiddleware
|
|
||||||
*/
|
|
||||||
public function testResolveMiddlewareNoContainer()
|
|
||||||
{
|
|
||||||
/** @var ServerRequestInterface|MockObject $request */
|
|
||||||
$request = $this->createMock(ServerRequestInterface::class);
|
|
||||||
|
|
||||||
$this->expectException(InvalidArgumentException::class);
|
|
||||||
|
|
||||||
$dispatcher = new Dispatcher([ReturnResponseMiddleware::class]);
|
|
||||||
$dispatcher->handle($request);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,11 @@ class LegacyMiddlewareTest extends TestCase
|
||||||
['title2', 'content2']
|
['title2', 'content2']
|
||||||
);
|
);
|
||||||
|
|
||||||
$middleware->expects($this->exactly(2))
|
$middleware->expects($this->exactly(3))
|
||||||
->method('renderPage')
|
->method('renderPage')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
['user_worklog', 'title', 'content'],
|
['user_worklog', 'title', 'content'],
|
||||||
|
['404', 'Page not found'],
|
||||||
['login', 'title2', 'content2']
|
['login', 'title2', 'content2']
|
||||||
)
|
)
|
||||||
->willReturn($response);
|
->willReturn($response);
|
||||||
|
@ -73,11 +74,6 @@ class LegacyMiddlewareTest extends TestCase
|
||||||
'/'
|
'/'
|
||||||
);
|
);
|
||||||
|
|
||||||
$handler->expects($this->once())
|
|
||||||
->method('handle')
|
|
||||||
->with($request)
|
|
||||||
->willReturn($response);
|
|
||||||
|
|
||||||
$middleware->process($request, $handler);
|
$middleware->process($request, $handler);
|
||||||
$middleware->process($request, $handler);
|
$middleware->process($request, $handler);
|
||||||
$middleware->process($request, $handler);
|
$middleware->process($request, $handler);
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Engelsystem\Test\Unit\Middleware;
|
|
||||||
|
|
||||||
use Engelsystem\Middleware\NotFoundResponse;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
|
||||||
|
|
||||||
class NotFoundResponseTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @covers \Engelsystem\Middleware\NotFoundResponse::process
|
|
||||||
*/
|
|
||||||
public function testRegister()
|
|
||||||
{
|
|
||||||
/** @var NotFoundResponse|MockObject $middleware */
|
|
||||||
$middleware = $this->getMockBuilder(NotFoundResponse::class)
|
|
||||||
->setMethods(['renderPage'])
|
|
||||||
->getMock();
|
|
||||||
/** @var ResponseInterface|MockObject $response */
|
|
||||||
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
|
||||||
/** @var RequestHandlerInterface|MockObject $handler */
|
|
||||||
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
|
||||||
/** @var ServerRequestInterface|MockObject $request */
|
|
||||||
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
|
||||||
|
|
||||||
$middleware->expects($this->once())
|
|
||||||
->method('renderPage')
|
|
||||||
->willReturn($response);
|
|
||||||
|
|
||||||
$handler->expects($this->never())
|
|
||||||
->method('handle');
|
|
||||||
|
|
||||||
$middleware->process($request, $handler);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Middleware\RequestHandler;
|
||||||
|
use Engelsystem\Middleware\RequestHandlerServiceProvider;
|
||||||
|
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
|
||||||
|
class RequestHandlerServiceProviderTest extends ServiceProviderTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RequestHandlerServiceProvider::register()
|
||||||
|
*/
|
||||||
|
public function testRegister()
|
||||||
|
{
|
||||||
|
/** @var RequestHandler|MockObject $requestHandler */
|
||||||
|
$requestHandler = $this->createMock(RequestHandler::class);
|
||||||
|
|
||||||
|
$app = $this->getApp(['make', 'instance', 'bind']);
|
||||||
|
|
||||||
|
$app->expects($this->once())
|
||||||
|
->method('make')
|
||||||
|
->with(RequestHandler::class)
|
||||||
|
->willReturn($requestHandler);
|
||||||
|
$app->expects($this->once())
|
||||||
|
->method('instance')
|
||||||
|
->with('request.handler', $requestHandler);
|
||||||
|
$app->expects($this->once())
|
||||||
|
->method('bind')
|
||||||
|
->with(RequestHandler::class, 'request.handler');
|
||||||
|
|
||||||
|
$serviceProvider = new RequestHandlerServiceProvider($app);
|
||||||
|
$serviceProvider->register();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Application;
|
||||||
|
use Engelsystem\Middleware\RequestHandler;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use ReflectionClass as Reflection;
|
||||||
|
|
||||||
|
class RequestHandlerTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RequestHandler::__construct
|
||||||
|
*/
|
||||||
|
public function testInit()
|
||||||
|
{
|
||||||
|
/** @var Application|MockObject $container */
|
||||||
|
$container = $this->createMock(Application::class);
|
||||||
|
|
||||||
|
$handler = new RequestHandler($container);
|
||||||
|
|
||||||
|
$reflection = new Reflection(get_class($handler));
|
||||||
|
$property = $reflection->getProperty('container');
|
||||||
|
$property->setAccessible(true);
|
||||||
|
|
||||||
|
$this->assertEquals($container, $property->getValue($handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RequestHandler::process
|
||||||
|
*/
|
||||||
|
public function testProcess()
|
||||||
|
{
|
||||||
|
/** @var Application|MockObject $container */
|
||||||
|
$container = $this->createMock(Application::class);
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||||
|
|
||||||
|
$middlewareInterface = $this->getMockForAbstractClass(MiddlewareInterface::class);
|
||||||
|
$requestHandlerInterface = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||||
|
|
||||||
|
$request->expects($this->exactly(3))
|
||||||
|
->method('getAttribute')
|
||||||
|
->with('route-request-handler')
|
||||||
|
->willReturn('FooBarClass');
|
||||||
|
|
||||||
|
/** @var RequestHandler|MockObject $middleware */
|
||||||
|
$middleware = $this->getMockBuilder(RequestHandler::class)
|
||||||
|
->setConstructorArgs([$container])
|
||||||
|
->setMethods(['resolveMiddleware'])
|
||||||
|
->getMock();
|
||||||
|
$middleware->expects($this->exactly(3))
|
||||||
|
->method('resolveMiddleware')
|
||||||
|
->with('FooBarClass')
|
||||||
|
->willReturnOnConsecutiveCalls(
|
||||||
|
$middlewareInterface,
|
||||||
|
$requestHandlerInterface,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
$middlewareInterface->expects($this->once())
|
||||||
|
->method('process')
|
||||||
|
->with($request, $handler)
|
||||||
|
->willReturn($response);
|
||||||
|
$requestHandlerInterface->expects($this->once())
|
||||||
|
->method('handle')
|
||||||
|
->with($request)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$return = $middleware->process($request, $handler);
|
||||||
|
$this->assertEquals($return, $response);
|
||||||
|
|
||||||
|
$middleware->process($request, $handler);
|
||||||
|
$this->assertEquals($return, $response);
|
||||||
|
|
||||||
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
$middleware->process($request, $handler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Application;
|
||||||
|
use Engelsystem\Middleware\CallableHandler;
|
||||||
|
use Engelsystem\Test\Unit\Middleware\Stub\HasStaticMethod;
|
||||||
|
use Engelsystem\Test\Unit\Middleware\Stub\ResolvesMiddlewareTraitImplementation;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
|
||||||
|
class ResolvesMiddlewareTraitTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\ResolvesMiddlewareTrait::resolveMiddleware
|
||||||
|
* @covers \Engelsystem\Middleware\ResolvesMiddlewareTrait::isMiddleware
|
||||||
|
*/
|
||||||
|
public function testResolveMiddleware()
|
||||||
|
{
|
||||||
|
/** @var Application|MockObject $container */
|
||||||
|
$container = $this->createMock(Application::class);
|
||||||
|
$middlewareInterface = $this->getMockForAbstractClass(MiddlewareInterface::class);
|
||||||
|
$callable = [HasStaticMethod::class, 'foo'];
|
||||||
|
|
||||||
|
$container->expects($this->exactly(3))
|
||||||
|
->method('make')
|
||||||
|
->withConsecutive(
|
||||||
|
['FooBarClass'],
|
||||||
|
[CallableHandler::class, ['callable' => $callable]],
|
||||||
|
['UnresolvableClass']
|
||||||
|
)
|
||||||
|
->willReturnOnConsecutiveCalls(
|
||||||
|
$middlewareInterface,
|
||||||
|
$middlewareInterface,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
$middleware = new ResolvesMiddlewareTraitImplementation($container);
|
||||||
|
|
||||||
|
$return = $middleware->callResolveMiddleware('FooBarClass');
|
||||||
|
$this->assertEquals($middlewareInterface, $return);
|
||||||
|
|
||||||
|
$return = $middleware->callResolveMiddleware($callable);
|
||||||
|
$this->assertEquals($middlewareInterface, $return);
|
||||||
|
|
||||||
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
$middleware->callResolveMiddleware('UnresolvableClass');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\ResolvesMiddlewareTrait::resolveMiddleware
|
||||||
|
*/
|
||||||
|
public function testResolveMiddlewareNoContainer()
|
||||||
|
{
|
||||||
|
$middlewareInterface = $this->getMockForAbstractClass(MiddlewareInterface::class);
|
||||||
|
|
||||||
|
$middleware = new ResolvesMiddlewareTraitImplementation();
|
||||||
|
$return = $middleware->callResolveMiddleware($middlewareInterface);
|
||||||
|
|
||||||
|
$this->assertEquals($middlewareInterface, $return);
|
||||||
|
|
||||||
|
$this->expectException(InvalidArgumentException::class);
|
||||||
|
$middleware->callResolveMiddleware('FooBarClass');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Middleware\LegacyMiddleware;
|
||||||
|
use Engelsystem\Middleware\RouteDispatcher;
|
||||||
|
use Engelsystem\Middleware\RouteDispatcherServiceProvider;
|
||||||
|
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||||
|
use FastRoute\Dispatcher as FastRouteDispatcher;
|
||||||
|
use Illuminate\Contracts\Container\ContextualBindingBuilder;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
|
||||||
|
class RouteDispatcherServiceProviderTest extends ServiceProviderTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RouteDispatcherServiceProvider::register()
|
||||||
|
*/
|
||||||
|
public function testRegister()
|
||||||
|
{
|
||||||
|
$bindingBuilder = $this->createMock(ContextualBindingBuilder::class);
|
||||||
|
$routeDispatcher = $this->getMockForAbstractClass(FastRouteDispatcher::class);
|
||||||
|
|
||||||
|
$app = $this->getApp(['alias', 'when']);
|
||||||
|
|
||||||
|
$app->expects($this->once())
|
||||||
|
->method('alias')
|
||||||
|
->with(RouteDispatcher::class, 'route.dispatcher');
|
||||||
|
|
||||||
|
$app->expects($this->exactly(2))
|
||||||
|
->method('when')
|
||||||
|
->with(RouteDispatcher::class)
|
||||||
|
->willReturn($bindingBuilder);
|
||||||
|
|
||||||
|
$bindingBuilder->expects($this->exactly(2))
|
||||||
|
->method('needs')
|
||||||
|
->withConsecutive(
|
||||||
|
[FastRouteDispatcher::class],
|
||||||
|
[MiddlewareInterface::class]
|
||||||
|
)
|
||||||
|
->willReturn($bindingBuilder);
|
||||||
|
|
||||||
|
$bindingBuilder->expects($this->exactly(2))
|
||||||
|
->method('give')
|
||||||
|
->with($this->callback(function ($subject) {
|
||||||
|
if (is_callable($subject)) {
|
||||||
|
$subject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_callable($subject) || $subject == LegacyMiddleware::class;
|
||||||
|
}));
|
||||||
|
|
||||||
|
/** @var RouteDispatcherServiceProvider|MockObject $serviceProvider */
|
||||||
|
$serviceProvider = $this->getMockBuilder(RouteDispatcherServiceProvider::class)
|
||||||
|
->setConstructorArgs([$app])
|
||||||
|
->setMethods(['generateRouting'])
|
||||||
|
->getMock();
|
||||||
|
|
||||||
|
$serviceProvider->expects($this->once())
|
||||||
|
->method('generateRouting')
|
||||||
|
->willReturn($routeDispatcher);
|
||||||
|
|
||||||
|
$serviceProvider->register();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware;
|
||||||
|
|
||||||
|
use Engelsystem\Middleware\RouteDispatcher;
|
||||||
|
use FastRoute\Dispatcher as FastRouteDispatcher;
|
||||||
|
use PHPUnit\Framework\MockObject\MockObject;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
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;
|
||||||
|
|
||||||
|
class RouteDispatcherTest extends TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RouteDispatcher::process
|
||||||
|
* @covers \Engelsystem\Middleware\RouteDispatcher::__construct
|
||||||
|
*/
|
||||||
|
public function testProcess()
|
||||||
|
{
|
||||||
|
/** @var FastRouteDispatcher|MockObject $dispatcher */
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
list($dispatcher, $response, $request, $handler) = $this->getMocks();
|
||||||
|
|
||||||
|
$dispatcher->expects($this->once())
|
||||||
|
->method('dispatch')
|
||||||
|
->with('HEAD', '/foo!bar')
|
||||||
|
->willReturn([FastRouteDispatcher::FOUND, $handler, ['foo' => 'bar', 'lorem' => 'ipsum']]);
|
||||||
|
|
||||||
|
$request->expects($this->exactly(3))
|
||||||
|
->method('withAttribute')
|
||||||
|
->withConsecutive(
|
||||||
|
['route-request-handler', $handler],
|
||||||
|
['foo', 'bar'],
|
||||||
|
['lorem', 'ipsum']
|
||||||
|
)
|
||||||
|
->willReturn($request);
|
||||||
|
|
||||||
|
$handler->expects($this->once())
|
||||||
|
->method('handle')
|
||||||
|
->with($request)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$middleware = new RouteDispatcher($dispatcher, $response);
|
||||||
|
$return = $middleware->process($request, $handler);
|
||||||
|
$this->assertEquals($response, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RouteDispatcher::process
|
||||||
|
*/
|
||||||
|
public function testProcessNotFound()
|
||||||
|
{
|
||||||
|
/** @var FastRouteDispatcher|MockObject $dispatcher */
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
list($dispatcher, $response, $request, $handler) = $this->getMocks();
|
||||||
|
/** @var MiddlewareInterface|MockObject $notFound */
|
||||||
|
$notFound = $this->createMock(MiddlewareInterface::class);
|
||||||
|
|
||||||
|
$dispatcher->expects($this->exactly(2))
|
||||||
|
->method('dispatch')
|
||||||
|
->with('HEAD', '/foo!bar')
|
||||||
|
->willReturn([FastRouteDispatcher::NOT_FOUND]);
|
||||||
|
|
||||||
|
$response->expects($this->once())
|
||||||
|
->method('withStatus')
|
||||||
|
->with(404)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$notFound->expects($this->once())
|
||||||
|
->method('process')
|
||||||
|
->with($request, $handler)
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$middleware = new RouteDispatcher($dispatcher, $response, $notFound);
|
||||||
|
$return = $middleware->process($request, $handler);
|
||||||
|
$this->assertEquals($response, $return);
|
||||||
|
|
||||||
|
$middleware = new RouteDispatcher($dispatcher, $response);
|
||||||
|
$return = $middleware->process($request, $handler);
|
||||||
|
$this->assertEquals($response, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @covers \Engelsystem\Middleware\RouteDispatcher::process
|
||||||
|
*/
|
||||||
|
public function testProcessNotAllowed()
|
||||||
|
{
|
||||||
|
/** @var FastRouteDispatcher|MockObject $dispatcher */
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
list($dispatcher, $response, $request, $handler) = $this->getMocks();
|
||||||
|
|
||||||
|
$dispatcher->expects($this->once())
|
||||||
|
->method('dispatch')
|
||||||
|
->with('HEAD', '/foo!bar')
|
||||||
|
->willReturn([FastRouteDispatcher::METHOD_NOT_ALLOWED, ['POST', 'TEST']]);
|
||||||
|
|
||||||
|
$response->expects($this->once())
|
||||||
|
->method('withStatus')
|
||||||
|
->with(405)
|
||||||
|
->willReturn($response);
|
||||||
|
$response->expects($this->once())
|
||||||
|
->method('withHeader')
|
||||||
|
->with('Allow', 'POST, TEST')
|
||||||
|
->willReturn($response);
|
||||||
|
|
||||||
|
$middleware = new RouteDispatcher($dispatcher, $response);
|
||||||
|
$return = $middleware->process($request, $handler);
|
||||||
|
$this->assertEquals($response, $return);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function getMocks(): array
|
||||||
|
{
|
||||||
|
/** @var FastRouteDispatcher|MockObject $dispatcher */
|
||||||
|
$dispatcher = $this->getMockForAbstractClass(FastRouteDispatcher::class);
|
||||||
|
/** @var ResponseInterface|MockObject $response */
|
||||||
|
$response = $this->getMockForAbstractClass(ResponseInterface::class);
|
||||||
|
/** @var ServerRequestInterface|MockObject $request */
|
||||||
|
$request = $this->getMockForAbstractClass(ServerRequestInterface::class);
|
||||||
|
/** @var RequestHandlerInterface|MockObject $handler */
|
||||||
|
$handler = $this->getMockForAbstractClass(RequestHandlerInterface::class);
|
||||||
|
/** @var UriInterface|MockObject $uriInterface */
|
||||||
|
$uriInterface = $this->getMockForAbstractClass(UriInterface::class);
|
||||||
|
|
||||||
|
$request->expects($this->atLeastOnce())
|
||||||
|
->method('getMethod')
|
||||||
|
->willReturn('HEAD');
|
||||||
|
$request->expects($this->atLeastOnce())
|
||||||
|
->method('getUri')
|
||||||
|
->willReturn($uriInterface);
|
||||||
|
$uriInterface->expects($this->atLeastOnce())
|
||||||
|
->method('getPath')
|
||||||
|
->willReturn('/foo%21bar');
|
||||||
|
|
||||||
|
return array($dispatcher, $response, $request, $handler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware\Stub;
|
||||||
|
|
||||||
|
class HasStaticMethod
|
||||||
|
{
|
||||||
|
public static function foo() { }
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Engelsystem\Test\Unit\Middleware\Stub;
|
||||||
|
|
||||||
|
use Engelsystem\Application;
|
||||||
|
use Engelsystem\Middleware\ResolvesMiddlewareTrait;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
|
||||||
|
class ResolvesMiddlewareTraitImplementation
|
||||||
|
{
|
||||||
|
use ResolvesMiddlewareTrait;
|
||||||
|
|
||||||
|
/** @var Application */
|
||||||
|
protected $container;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Application $container
|
||||||
|
*/
|
||||||
|
public function __construct(Application $container = null)
|
||||||
|
{
|
||||||
|
$this->container = $container;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|callable|MiddlewareInterface|RequestHandlerInterface $middleware
|
||||||
|
* @return MiddlewareInterface|RequestHandlerInterface
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function callResolveMiddleware($middleware)
|
||||||
|
{
|
||||||
|
return $this->resolveMiddleware($middleware);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue