From a1bc763a16ee8be109de5c9053fbc5eded53824e Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Sat, 25 Aug 2018 21:16:20 +0200 Subject: Added nikic/fast-route as routing dispatcher --- src/Middleware/CallableHandler.php | 77 +++++++++++++++++++++++ src/Middleware/Dispatcher.php | 26 +------- src/Middleware/LegacyMiddleware.php | 13 +++- src/Middleware/NotFoundResponse.php | 56 ----------------- src/Middleware/RequestHandler.php | 50 +++++++++++++++ src/Middleware/RequestHandlerServiceProvider.php | 17 +++++ src/Middleware/ResolvesMiddlewareTrait.php | 56 +++++++++++++++++ src/Middleware/RouteDispatcher.php | 75 ++++++++++++++++++++++ src/Middleware/RouteDispatcherServiceProvider.php | 41 ++++++++++++ 9 files changed, 330 insertions(+), 81 deletions(-) create mode 100644 src/Middleware/CallableHandler.php delete mode 100644 src/Middleware/NotFoundResponse.php create mode 100644 src/Middleware/RequestHandler.php create mode 100644 src/Middleware/RequestHandlerServiceProvider.php create mode 100644 src/Middleware/ResolvesMiddlewareTrait.php create mode 100644 src/Middleware/RouteDispatcher.php create mode 100644 src/Middleware/RouteDispatcherServiceProvider.php (limited to 'src/Middleware') diff --git a/src/Middleware/CallableHandler.php b/src/Middleware/CallableHandler.php new file mode 100644 index 00000000..eb493bf1 --- /dev/null +++ b/src/Middleware/CallableHandler.php @@ -0,0 +1,77 @@ +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); + } +} diff --git a/src/Middleware/Dispatcher.php b/src/Middleware/Dispatcher.php index f2a5b5d5..48eb0948 100644 --- a/src/Middleware/Dispatcher.php +++ b/src/Middleware/Dispatcher.php @@ -12,6 +12,8 @@ use Psr\Http\Server\RequestHandlerInterface; class Dispatcher implements MiddlewareInterface, RequestHandlerInterface { + use ResolvesMiddlewareTrait; + /** @var MiddlewareInterface[]|string[] */ protected $stack; @@ -70,10 +72,7 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface throw new LogicException('Middleware queue is empty'); } - if (is_string($middleware)) { - $middleware = $this->resolveMiddleware($middleware); - } - + $middleware = $this->resolveMiddleware($middleware); if (!$middleware instanceof MiddlewareInterface) { throw new InvalidArgumentException('Middleware is no instance of ' . MiddlewareInterface::class); } @@ -81,25 +80,6 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface 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 */ diff --git a/src/Middleware/LegacyMiddleware.php b/src/Middleware/LegacyMiddleware.php index 714141de..276fb3ee 100644 --- a/src/Middleware/LegacyMiddleware.php +++ b/src/Middleware/LegacyMiddleware.php @@ -83,7 +83,9 @@ class LegacyMiddleware implements MiddlewareInterface } 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); @@ -270,10 +272,17 @@ class LegacyMiddleware implements MiddlewareInterface $parameters = [ 'key' => (isset($user) ? $user['api_key'] : ''), ]; + if ($page == 'user_meetings') { $parameters['meetings'] = 1; } + $status = 200; + if ($page == '404') { + $status = 404; + $content = info($content, true); + } + return response(view(__DIR__ . '/../../templates/layout.html', [ 'theme' => isset($user) ? $user['color'] : config('theme'), 'title' => $title, @@ -291,6 +300,6 @@ class LegacyMiddleware implements MiddlewareInterface 'contact_email' => config('contact_email'), 'locale' => locale(), 'event_info' => EventConfig_info($event_config) . '
' - ])); + ]), $status); } } diff --git a/src/Middleware/NotFoundResponse.php b/src/Middleware/NotFoundResponse.php deleted file mode 100644 index f9431c1d..00000000 --- a/src/Middleware/NotFoundResponse.php +++ /dev/null @@ -1,56 +0,0 @@ -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) . '
' - ]), 404); - } -} diff --git a/src/Middleware/RequestHandler.php b/src/Middleware/RequestHandler.php new file mode 100644 index 00000000..e1381abf --- /dev/null +++ b/src/Middleware/RequestHandler.php @@ -0,0 +1,50 @@ +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)); + } +} diff --git a/src/Middleware/RequestHandlerServiceProvider.php b/src/Middleware/RequestHandlerServiceProvider.php new file mode 100644 index 00000000..c6488118 --- /dev/null +++ b/src/Middleware/RequestHandlerServiceProvider.php @@ -0,0 +1,17 @@ +app->make(RequestHandler::class); + + $this->app->instance('request.handler', $requestHandler); + $this->app->bind(RequestHandler::class, 'request.handler'); + } +} diff --git a/src/Middleware/ResolvesMiddlewareTrait.php b/src/Middleware/ResolvesMiddlewareTrait.php new file mode 100644 index 00000000..76557ce6 --- /dev/null +++ b/src/Middleware/ResolvesMiddlewareTrait.php @@ -0,0 +1,56 @@ +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); + } +} diff --git a/src/Middleware/RouteDispatcher.php b/src/Middleware/RouteDispatcher.php new file mode 100644 index 00000000..f14faea8 --- /dev/null +++ b/src/Middleware/RouteDispatcher.php @@ -0,0 +1,75 @@ +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); + } +} diff --git a/src/Middleware/RouteDispatcherServiceProvider.php b/src/Middleware/RouteDispatcherServiceProvider.php new file mode 100644 index 00000000..3b4fa183 --- /dev/null +++ b/src/Middleware/RouteDispatcherServiceProvider.php @@ -0,0 +1,41 @@ +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'); + }); + } +} -- cgit v1.2.3-54-g00ecf