From 9d8ab043488082ce2e396731137ec907bcc6dc7d Mon Sep 17 00:00:00 2001 From: eater <=@eater.me> Date: Mon, 27 Aug 2018 17:22:47 +0200 Subject: [PATCH] Fix some things --- composer.json | 4 +-- config/default.php | 13 ++++---- src/Context.php | 26 ++++++++++------ src/Server.php | 78 +++++++++++++++++++++++++++++++++------------- src/functions.php | 12 +++---- 5 files changed, 87 insertions(+), 46 deletions(-) diff --git a/composer.json b/composer.json index f863dbd..8b00f03 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,5 @@ { "name": "bitcommunism/http", - "version": "1.0.1", "license": "MIT", "require": { "nikic/fast-route": "^1.2", @@ -10,6 +9,7 @@ "autoload": { "psr-4": { "BitCommunism\\Http\\": "src/" - } + }, + "files": ["src/functions.php"] } } \ No newline at end of file diff --git a/config/default.php b/config/default.php index 904da68..9bc8030 100644 --- a/config/default.php +++ b/config/default.php @@ -2,24 +2,23 @@ namespace BitCommunism\Http; -use BitCommunism\Marx\Instance; use function DI\add; use function DI\autowire; use function DI\get; -use function DI\object; +use function DI\value; return [ 'marx.calls' => add([ - 'http' => function(Server $server) { + 'http' => value(function(Server $server) { return $server; - } + }) ]), 'marx.loaders' => add([ - function(Server $server) { + value(function(Server $server) { $server->buildRoutes(); - } + }) ]), - Server::class => object()->constructorParameter('routes', get('routes')), + Server::class => autowire()->constructorParameter('routes', get('routes')), ]; \ No newline at end of file diff --git a/src/Context.php b/src/Context.php index 17b523c..db20f17 100644 --- a/src/Context.php +++ b/src/Context.php @@ -7,7 +7,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -class Context +class Context implements \ArrayAccess { /** * @var ServerRequestInterface @@ -112,29 +112,37 @@ class Context return $this->settings; } + /** + * @param array $settings + */ + public function setSettings(array $settings): void + { + $this->settings = $settings; + } + public function redirect($to, $status = 302): void { $this->withResponse(function (ResponseInterface $response) use ($to, $status) { return $response->withStatus($status)->withHeader('Location', $to); }); } - public function __get($name) + public function offsetExists($offset) { - return $this->context[$name]; + return isset($this->context[$offset]); } - public function __set($name, $value) + public function offsetGet($offset) { - $this->context[$name] = $value; + return $this->context[$offset]; } - public function __isset($name) + public function offsetSet($offset, $value) { - return isset($this->context[$name]); + $this->context[$offset] = $value; } - public function __unset($name) + public function offsetUnset($offset) { - unset($this->context[$name]); + unset($this->context[$offset]); } } \ No newline at end of file diff --git a/src/Server.php b/src/Server.php index 26d18c9..1e1ef26 100644 --- a/src/Server.php +++ b/src/Server.php @@ -4,23 +4,31 @@ namespace BitCommunism\Http; use DI\Container; -use DI\ContainerBuilder; -use function DI\value; use FastRoute\Dispatcher; use FastRoute\RouteCollector; -use function FastRoute\simpleDispatcher; -use function GuzzleHttp\Psr7\copy_to_stream; use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\ServerRequest; -use function GuzzleHttp\Psr7\stream_for; -use Psr\Http\Message\RequestInterface; +use Invoker\Invoker; +use Invoker\ParameterResolver\AssociativeArrayResolver; +use Invoker\ParameterResolver\Container\TypeHintContainerResolver; +use Invoker\ParameterResolver\DefaultValueResolver; +use Invoker\ParameterResolver\NumericArrayResolver; +use Invoker\ParameterResolver\ResolverChain; +use Invoker\ParameterResolver\TypeHintResolver; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; +use function FastRoute\simpleDispatcher; +use function GuzzleHttp\Psr7\copy_to_stream; +use function GuzzleHttp\Psr7\stream_for; class Server { private $routes = []; private $container; + /** + * @var Invoker + */ + private $invoker; /** * @var Dispatcher @@ -31,6 +39,7 @@ class Server { $this->routes = $routes; $this->container = $container; + $this->invoker = $this->createDefaultInvoker(); } private function iterateRoutes() @@ -40,17 +49,26 @@ class Server private function iterateRoutesFromArray($routeArr, $prefix = '', $known = [], $middleware = []) { + $route = $routeArr['middleware'] ?? []; + $middleware = array_merge($middleware, array_map(function ($route) { + if (!$route instanceof Handle) { + return new Handle($route); + } + + return $route; + }, (array)$route)); + foreach ($routeArr as $key => $route) { if ($key === 'middleware') { - $middleware = array_merge($middleware, $route); + continue; } if (is_array($route) && !(isset($route[0]) && isset($route[1]))) { - yield from $this->iterateRoutesFromArray($route, $prefix . $key, $known); + yield from $this->iterateRoutesFromArray($route, $prefix . $key, $known, $middleware); continue; } - if (is_array($route) || is_string($route)) { + if (!$route instanceof Handle) { $route = new Handle($route); } @@ -123,6 +141,16 @@ class Server return $response; } + private function createDefaultInvoker() { + return new Invoker(new ResolverChain(array( + new NumericArrayResolver(), + new AssociativeArrayResolver(), + new DefaultValueResolver(), + new TypeHintResolver(), + new TypeHintContainerResolver($this->container), + )), $this->container); + } + public function handleHttp(ServerRequestInterface $request, Handle $handler, array $vars, ResponseInterface $response = null): ResponseInterface { $middlewareArray = $handler->getMiddleware(); @@ -134,29 +162,33 @@ class Server $response = new Response(200, [], stream_for('Empty response')); } - $context = new Context($request, $response); + $context = new Context($request, $response, $vars); $next = function (Context $context) use ($handler, $middlewareArray, &$middlewarePointer, &$next) { $output = null; - if (count($middlewareArray) >= $middlewarePointer) { - $call = $handler->getCall(); - if (is_array($call)) { - $obj = $this->container->get($call[0]); - $call = [$obj, $call[1]]; - } - } else { - [$name, $func] = $middlewareArray[$middlewarePointer++]; - $middleware = $this->container->get($name); - $call = [$middleware, $func]; + if (count($middlewareArray) > $middlewarePointer) { + $handler = $middlewareArray[$middlewarePointer++]; + } + + $call = $handler->getCall(); + if (is_array($call)) { + $obj = $this->container->get($call[0]); + $call = [$obj, $call[1]]; } - $output = $this->container->call($call, [ + $context->setSettings($handler->getSettings()); + + $output = $this->invoker->call($call, [ 'request' => $context->getRequest(), + ServerRequestInterface::class => $context->getRequest(), 'response' => $context->getResponse(), + ResponseInterface::class => $context->getResponse(), 'context' => $context, + Context::class => $context, 'vars' => $context->getVars(), 'settings' => $context->getSettings(), + 'next' => $next, ]); $this->normalizeResponse($output, $context); @@ -169,6 +201,10 @@ class Server private function normalizeResponse($response, Context $context) { + if ($response === null) { + return; + } + if ($response instanceof ResponseInterface) { $context->setResponse($response); return; diff --git a/src/functions.php b/src/functions.php index debc2ef..0cd6528 100644 --- a/src/functions.php +++ b/src/functions.php @@ -2,20 +2,18 @@ namespace BitCommunism\Http; -use Psr\Http\Message\ResponseInterface; - -if (function_exists(__NAMESPACE__ . '\\handle')) { - function handle($call, $settings = []) +if (!function_exists(__NAMESPACE__ . '\\handle')) { + function handle($call, $settings = []): Handle { return new Handle($call, $settings); } } -if (function_exists(__NAMESPACE__ . '\\redirect')) { +if (!function_exists(__NAMESPACE__ . '\\redirect')) { function redirect($to, $status = 302) { - return function (Context $c) use ($to, $status) { + return handle(function (Context $c) use ($to, $status) { $c->redirect($to, $status); - }; + }); } } \ No newline at end of file