diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Http/LegacyUrlGenerator.php (renamed from src/Routing/LegacyUrlGenerator.php) | 6 | ||||
-rw-r--r-- | src/Http/UrlGenerator.php (renamed from src/Routing/UrlGenerator.php) | 4 | ||||
-rw-r--r-- | src/Http/UrlGeneratorInterface.php (renamed from src/Routing/UrlGeneratorInterface.php) | 4 | ||||
-rw-r--r-- | src/Http/UrlGeneratorServiceProvider.php | 14 | ||||
-rw-r--r-- | src/Middleware/CallableHandler.php | 77 | ||||
-rw-r--r-- | src/Middleware/Dispatcher.php | 26 | ||||
-rw-r--r-- | src/Middleware/LegacyMiddleware.php | 13 | ||||
-rw-r--r-- | src/Middleware/NotFoundResponse.php | 56 | ||||
-rw-r--r-- | src/Middleware/RequestHandler.php | 50 | ||||
-rw-r--r-- | src/Middleware/RequestHandlerServiceProvider.php | 17 | ||||
-rw-r--r-- | src/Middleware/ResolvesMiddlewareTrait.php | 56 | ||||
-rw-r--r-- | src/Middleware/RouteDispatcher.php | 75 | ||||
-rw-r--r-- | src/Middleware/RouteDispatcherServiceProvider.php | 41 | ||||
-rw-r--r-- | src/Routing/RoutingServiceProvider.php | 24 | ||||
-rw-r--r-- | src/helpers.php | 6 |
15 files changed, 354 insertions, 115 deletions
diff --git a/src/Routing/LegacyUrlGenerator.php b/src/Http/LegacyUrlGenerator.php index fdac4f96..b9f8b7f1 100644 --- a/src/Routing/LegacyUrlGenerator.php +++ b/src/Http/LegacyUrlGenerator.php @@ -1,6 +1,6 @@ <?php -namespace Engelsystem\Routing; +namespace Engelsystem\Http; /** * Provides urls when webserver rewriting is disabled. @@ -14,7 +14,7 @@ class LegacyUrlGenerator extends UrlGenerator * @param array $parameters * @return string urls in the form <app url>/index.php?p=<path>&<parameters> */ - public function linkTo($path, $parameters = []) + public function to($path, $parameters = []) { $page = ltrim($path, '/'); if (!empty($page)) { @@ -22,7 +22,7 @@ class LegacyUrlGenerator extends UrlGenerator $parameters = array_merge(['p' => $page], $parameters); } - $uri = parent::linkTo('index.php', $parameters); + $uri = parent::to('index.php', $parameters); $uri = preg_replace('~(/index\.php)+~', '/index.php', $uri); $uri = preg_replace('~(/index\.php)$~', '/', $uri); diff --git a/src/Routing/UrlGenerator.php b/src/Http/UrlGenerator.php index 188bac3b..7ced769e 100644 --- a/src/Routing/UrlGenerator.php +++ b/src/Http/UrlGenerator.php @@ -1,6 +1,6 @@ <?php -namespace Engelsystem\Routing; +namespace Engelsystem\Http; /** * Provides urls when rewriting on the webserver is enabled. (default) @@ -14,7 +14,7 @@ class UrlGenerator implements UrlGeneratorInterface * @param array $parameters * @return string url in the form [app url]/[path]?[parameters] */ - public function linkTo($path, $parameters = []) + public function to($path, $parameters = []) { $path = '/' . ltrim($path, '/'); $request = app('request'); diff --git a/src/Routing/UrlGeneratorInterface.php b/src/Http/UrlGeneratorInterface.php index f1a8ffed..b3b6b12d 100644 --- a/src/Routing/UrlGeneratorInterface.php +++ b/src/Http/UrlGeneratorInterface.php @@ -1,6 +1,6 @@ <?php -namespace Engelsystem\Routing; +namespace Engelsystem\Http; /** * To switch between different URL schemes. @@ -12,5 +12,5 @@ interface UrlGeneratorInterface * @param array $parameters * @return string */ - public function linkTo($path, $parameters = []); + public function to($path, $parameters = []); } diff --git a/src/Http/UrlGeneratorServiceProvider.php b/src/Http/UrlGeneratorServiceProvider.php new file mode 100644 index 00000000..37304076 --- /dev/null +++ b/src/Http/UrlGeneratorServiceProvider.php @@ -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); + } +} 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 @@ +<?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); + } +} 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); } @@ -82,25 +81,6 @@ class Dispatcher implements MiddlewareInterface, RequestHandlerInterface } /** - * 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 */ public function setContainer(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) . ' <br />' - ])); + ]), $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 @@ -<?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); - } -} 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 @@ +<?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)); + } +} 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 @@ +<?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'); + } +} 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 @@ +<?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); + } +} 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 @@ +<?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); + } +} 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 @@ +<?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'); + }); + } +} diff --git a/src/Routing/RoutingServiceProvider.php b/src/Routing/RoutingServiceProvider.php deleted file mode 100644 index beaa6a94..00000000 --- a/src/Routing/RoutingServiceProvider.php +++ /dev/null @@ -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'); - } -} diff --git a/src/helpers.php b/src/helpers.php index 50c5c837..95571a40 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -6,7 +6,7 @@ use Engelsystem\Config\Config; use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Renderer\Renderer; -use Engelsystem\Routing\UrlGeneratorInterface; +use Engelsystem\Http\UrlGenerator; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** @@ -125,13 +125,13 @@ function session($key = null, $default = null) */ function url($path = null, $parameters = []) { - $urlGenerator = app('routing.urlGenerator'); + $urlGenerator = app('http.urlGenerator'); if (is_null($path)) { return $urlGenerator; } - return $urlGenerator->linkTo($path, $parameters); + return $urlGenerator->to($path, $parameters); } /** |