Merge branch 'MyIgel-routing'
commit
2d6bca1357
@ -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,14 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Http;
|
||||
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
|
||||
class UrlGeneratorServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
$urlGenerator = $this->app->make(UrlGenerator::class);
|
||||
$this->app->instance('http.urlGenerator', $urlGenerator);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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');
|
||||
});
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
namespace Engelsystem\Routing;
|
||||
|
||||
use Engelsystem\Container\ServiceProvider;
|
||||
|
||||
/**
|
||||
* Registers the url generator depending on config.
|
||||
*/
|
||||
class RoutingServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
public function register()
|
||||
{
|
||||
$config = $this->app->get('config');
|
||||
$class = UrlGenerator::class;
|
||||
if (! $config->get('rewrite_urls', true)) {
|
||||
$class = LegacyUrlGenerator::class;
|
||||
}
|
||||
|
||||
$urlGenerator = $this->app->make($class);
|
||||
$this->app->instance('routing.urlGenerator', $urlGenerator);
|
||||
$this->app->bind(UrlGeneratorInterface::class, 'routing.urlGenerator');
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Http;
|
||||
|
||||
use Engelsystem\Http\UrlGenerator;
|
||||
use Engelsystem\Http\UrlGeneratorServiceProvider;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit_Framework_MockObject_MockObject;
|
||||
|
||||
class UrlGeneratorServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Http\UrlGeneratorServiceProvider::register()
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
/** @var PHPUnit_Framework_MockObject_MockObject|UrlGenerator $urlGenerator */
|
||||
$urlGenerator = $this->getMockBuilder(UrlGenerator::class)
|
||||
->getMock();
|
||||
|
||||
$app = $this->getApp();
|
||||
|
||||
$this->setExpects($app, 'make', [UrlGenerator::class], $urlGenerator);
|
||||
$this->setExpects($app, 'instance', ['http.urlGenerator', $urlGenerator]);
|
||||
|
||||
$serviceProvider = new UrlGeneratorServiceProvider($app);
|
||||
$serviceProvider->register();
|
||||
}
|
||||
}
|
@ -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 [$request, $response, $callable, $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 [$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);
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Engelsystem\Test\Unit\Routing;
|
||||
|
||||
use Engelsystem\Config\Config;
|
||||
use Engelsystem\Routing\LegacyUrlGenerator;
|
||||
use Engelsystem\Routing\RoutingServiceProvider;
|
||||
use Engelsystem\Routing\UrlGenerator;
|
||||
use Engelsystem\Routing\UrlGeneratorInterface;
|
||||
use Engelsystem\Test\Unit\ServiceProviderTest;
|
||||
use PHPUnit_Framework_MockObject_MockObject as MockObject;
|
||||
|
||||
class RoutingServiceProviderTest extends ServiceProviderTest
|
||||
{
|
||||
/**
|
||||
* @covers \Engelsystem\Routing\RoutingServiceProvider::register()
|
||||
*/
|
||||
public function testRegister()
|
||||
{
|
||||
$app = $this->getApp(['make', 'instance', 'bind', 'get']);
|
||||
/** @var MockObject|Config $config */
|
||||
$config = $this->getMockBuilder(Config::class)->getMock();
|
||||
/** @var MockObject|UrlGeneratorInterface $urlGenerator */
|
||||
$urlGenerator = $this->getMockForAbstractClass(UrlGeneratorInterface::class);
|
||||
/** @var MockObject|UrlGeneratorInterface $legacyUrlGenerator */
|
||||
$legacyUrlGenerator = $this->getMockForAbstractClass(UrlGeneratorInterface::class);
|
||||
|
||||
$config->expects($this->atLeastOnce())
|
||||
->method('get')
|
||||
->with('rewrite_urls')
|
||||
->willReturnOnConsecutiveCalls(
|
||||
true,
|
||||
false
|
||||
);
|
||||
|
||||
$this->setExpects($app, 'get', ['config'], $config, $this->atLeastOnce());
|
||||
|
||||
$app->expects($this->atLeastOnce())
|
||||
->method('make')
|
||||
->withConsecutive(
|
||||
[UrlGenerator::class],
|
||||
[LegacyUrlGenerator::class]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
$urlGenerator,
|
||||
$legacyUrlGenerator
|
||||
);
|
||||
$app->expects($this->atLeastOnce())
|
||||
->method('instance')
|
||||
->withConsecutive(
|
||||
['routing.urlGenerator', $urlGenerator],
|
||||
['routing.urlGenerator', $legacyUrlGenerator]
|
||||
);
|
||||
$this->setExpects(
|
||||
$app, 'bind',
|
||||
[UrlGeneratorInterface::class, 'routing.urlGenerator'], null,
|
||||
$this->atLeastOnce()
|
||||
);
|
||||
|
||||
$serviceProvider = new RoutingServiceProvider($app);
|
||||
$serviceProvider->register();
|
||||
$serviceProvider->register();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue