This commit is contained in:
as2252258@163.com
2021-09-05 03:56:04 +08:00
parent 8735203573
commit 9497909749
4 changed files with 278 additions and 183 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ class HandlerProviders extends BaseObject
* @param $method * @param $method
* @return mixed * @return mixed
*/ */
public static function get($path, $method): mixed public static function get($path, $method): ?Pipeline
{ {
return static::$handlers[$method][$path] ?? null; return static::$handlers[$method][$path] ?? null;
} }
+98 -77
View File
@@ -16,91 +16,112 @@ use Kiri\Abstracts\BaseObject;
class MiddlewareManager extends BaseObject class MiddlewareManager extends BaseObject
{ {
private static array $_middlewares = []; private static array $_middlewares = [];
/** /**
* @param $class * @param $class
* @param $method * @param $method
* @param array|string $middlewares * @param array|string $middlewares
*/ */
public static function addMiddlewares($class, $method, array|string $middlewares) public static function addMiddlewares($class, $method, array|string $middlewares)
{ {
if (is_object($class)) { if (is_object($class)) {
$class = $class::class; $class = $class::class;
} }
if (!isset(static::$_middlewares[$class . '::' . $method])) { if (!isset(static::$_middlewares[$class . '::' . $method])) {
static::$_middlewares[$class . '::' . $method] = []; static::$_middlewares[$class . '::' . $method] = [];
} }
if (is_string($middlewares) && !in_array($middlewares, static::$_middlewares[$class . '::' . $method])) { if (is_string($middlewares) && !in_array($middlewares, static::$_middlewares[$class . '::' . $method])) {
static::$_middlewares[$class . '::' . $method][] = $middlewares; static::$_middlewares[$class . '::' . $method][] = $middlewares;
return; return;
} }
foreach ($middlewares as $middleware) { foreach ($middlewares as $middleware) {
if (in_array($middleware, static::$_middlewares[$class . '::' . $method])) { if (in_array($middleware, static::$_middlewares[$class . '::' . $method])) {
continue; continue;
} }
static::$_middlewares[$class . '::' . $method][] = $middleware; static::$_middlewares[$class . '::' . $method][] = $middleware;
} }
} }
/** /**
* @param $class * @param $handler
* @param $method * @return mixed|null
* @return bool */
*/ public static function get($handler)
public static function hasMiddleware($class, $method): bool {
{ if ($handler instanceof Closure) {
if (is_object($class)) { return null;
$class = $class::class; }
} [$class, $method] = [$handler[0]::class, $handler[1]];
return isset(static::$_middlewares[$class . '::' . $method]); if (!static::hasMiddleware($class, $method)) {
} return null;
}
return static::$_middlewares[$class . '::' . $method];
}
/** /**
* @param $class * @param $class
* @param $method * @param $method
* @param $caller * @return bool
* @return mixed */
*/ public static function hasMiddleware($class, $method): bool
public static function callerMiddlewares($class, $method, $caller): mixed {
{ if (is_object($class)) {
if (is_object($class)) { $class = $class::class;
$class = $class::class; }
} return isset(static::$_middlewares[$class . '::' . $method]);
$middlewares = static::$_middlewares[$class . '::' . $method] ?? []; }
if (empty($middlewares)) {
return $caller;
}
return array_reduce(array_reverse($middlewares), function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if ($pipe instanceof MiddlewareInterface) {
return $pipe->onHandler($passable, $stack);
}
return call_user_func($pipe, $passable, $stack);
};
}, $caller);
}
/** /**
* @param $middlewares * @param $class
* @param Closure $caller * @param $method
* @return Closure * @param $caller
*/ * @return mixed
public static function closureMiddlewares($middlewares, Closure $caller): Closure */
{ public static function callerMiddlewares($class, $method, $caller): mixed
return array_reduce(array_reverse($middlewares), function ($stack, $pipe) { {
return function ($passable) use ($stack, $pipe) { if (is_object($class)) {
if ($pipe instanceof MiddlewareInterface) { $class = $class::class;
return $pipe->onHandler($passable, $stack); }
} $middlewares = static::$_middlewares[$class . '::' . $method] ?? [];
return call_user_func($pipe, $passable, $stack); if (empty($middlewares)) {
}; return $caller;
}, $caller); }
} return array_reduce(array_reverse($middlewares), function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if ($pipe instanceof MiddlewareInterface) {
$pipe = [$pipe, 'onHandler'];
}
return call_user_func($pipe, $passable, $stack);
};
}, $caller);
}
/**
* @param $middlewares
* @param Closure $caller
* @return Closure
*/
public static function closureMiddlewares($middlewares, Closure $caller): Closure
{
if (empty($middlewares)) {
return $caller;
}
return array_reduce(array_reverse($middlewares), function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if ($pipe instanceof MiddlewareInterface) {
$pipe = [$pipe, 'onHandler'];
}
return call_user_func($pipe, $passable, $stack);
};
}, $caller);
}
} }
+7 -105
View File
@@ -161,64 +161,16 @@ class Node
*/ */
private function injectMiddleware(string $method, $handler, $_injectParameters): void private function injectMiddleware(string $method, $handler, $_injectParameters): void
{ {
if (!($handler instanceof Closure)) { $callback = (new Pipeline())->overall($this->router->getMiddleware())
$callback = $this->injectControllerMiddleware($method, $handler, $_injectParameters); ->through($this->middleware[$method] ?? [])
} else { ->through(MiddlewareManager::get($handler))
$callback = $this->injectClosureMiddleware($method, $handler, $_injectParameters); ->send($_injectParameters)
} ->then($handler);
HandlerProviders::add($method, $this->sourcePath, $callback); HandlerProviders::add($method, $this->sourcePath, $callback);
} }
/**
* @param $method
* @param $handler
* @param $_injectParameters
* @return mixed
* @throws NotFindClassException
* @throws ReflectionException
* @throws Exception
*/
private function injectControllerMiddleware($method, $handler, $_injectParameters): mixed
{
$middleware = $this->middleware[$method] ?? [];
$allowMiddleware = $this->router->getMiddleware();
if (!empty($allowMiddleware)) {
array_unshift($middleware, $allowMiddleware);
}
MiddlewareManager::addMiddlewares($handler[0], $handler[1], $middleware);
return MiddlewareManager::callerMiddlewares(
$handler[0], $handler[1], $this->aopHandler($this->getAop($handler), $handler, $_injectParameters)
);
}
/**
* @param $method
* @param $handler
* @param $_injectParameters
* @return Closure
* @throws Exception
*/
private function injectClosureMiddleware($method, $handler, $_injectParameters): Closure
{
$middleware = $this->middleware[$method] ?? [];
$allowMiddleware = $this->router->getMiddleware();
if (!empty($allowMiddleware)) {
array_unshift($middleware, $allowMiddleware);
}
if (!empty($middleware)) {
return MiddlewareManager::closureMiddlewares($middleware,
$this->normalHandler($handler, $_injectParameters)
);
} else {
return $this->normalHandler($handler, $_injectParameters);
}
}
/** /**
* @throws ReflectionException * @throws ReflectionException
* @throws NotFindClassException * @throws NotFindClassException
@@ -236,56 +188,6 @@ class Node
} }
/**
* @param IAspect|null $reflect
* @param $handler
* @param $_injectParameters
* @return Closure
*/
#[Pure] private function aopHandler(?IAspect $reflect, $handler, $_injectParameters): Closure
{
if (is_null($reflect)) {
return $this->normalHandler($handler, $_injectParameters);
}
return static function () use ($reflect, $handler, $_injectParameters) {
return $reflect->invoke($handler, $_injectParameters);
};
}
/**
* @throws ReflectionException|NotFindClassException
*/
private function getAop($handler): ?IAspect
{
[$controller, $action] = $handler;
if (is_object($controller)) {
$controller = get_class($controller);
}
/** @var Aspect $aspect */
$aspect = NoteManager::getSpecify_annotation(Aspect::class, $controller, $action);
if (empty($aspect)) {
return null;
}
return di($aspect->aspect);
}
/**
* @param $handler
* @param $_injectParameters
* @return Closure
*/
private function normalHandler($handler, $_injectParameters): Closure
{
return static function () use ($handler, $_injectParameters) {
return call_user_func($handler, ...$_injectParameters);
};
}
/** /**
* @return array * @return array
*/ */
@@ -427,7 +329,7 @@ class Node
if (empty($handlerProviders)) { if (empty($handlerProviders)) {
throw new RequestException('<h2>HTTP 404 Not Found</h2><hr><i>Powered by Swoole</i>', 404); throw new RequestException('<h2>HTTP 404 Not Found</h2><hr><i>Powered by Swoole</i>', 404);
} }
return call_user_func($handlerProviders, request()); return $handlerProviders->interpreter();
} }
} }
+172
View File
@@ -0,0 +1,172 @@
<?php
namespace Http\Route;
use Annotation\Aspect;
use Closure;
use Http\IInterface\MiddlewareInterface;
use Kiri\Di\NoteManager;
use Kiri\Kiri;
use Throwable;
class Pipeline
{
protected $passable;
protected $overall;
protected $pipes = [];
protected $pipeline;
protected $exceptionHandler;
/**
* 初始数据
* @param $passable
* @return $this
*/
public function send($passable)
{
$this->passable = $passable;
return $this;
}
/**
* @param $middle
* @return $this
*/
public function overall($middle): static
{
$this->overall = $middle;
return $this;
}
/**
* 调用栈
* @param $pipes
* @return $this
*/
public function through($pipes)
{
if (empty($this->pipes)) {
$this->pipes = is_array($pipes) ? $pipes : func_get_args();
} else {
foreach ($pipes as $pipe) {
$this->pipes[] = $pipe;
}
}
return $this;
}
/**
* 执行
* @param Closure $destination
* @return mixed
*/
public function then(callable $destination)
{
$parameters = $this->passable;
if (!empty($this->overall)) {
array_unshift($this->pipes, $this->overall);
}
if (is_array($destination)) {
$destination = $this->aspect_caller($destination, $parameters);
}
$this->pipeline = array_reduce(array_reverse($this->pipes), $this->carry(),
static function () use ($destination, $parameters) {
return call_user_func($destination, ...$parameters);
}
);
return $this->clear();
}
/**
* @return $this
*/
private function clear()
{
$this->pipes = [];
$this->passable = null;
$this->overall = null;
return $this;
}
/**
* @param $destination
* @param $parameters
* @return \Closure
*/
private function aspect_caller($destination, $parameters)
{
[$controller, $action] = $destination;
/** @var \Annotation\Aspect $aop */
$aop = NoteManager::getSpecify_annotation(Aspect::class, $controller::class, $action);
if (!empty($aop)) {
$aop = Kiri::getDi()->get($aop->aspect);
$destination = static function () use ($aop, $destination, $parameters) {
/** @var \Kiri\IAspect $aop */
$aop->invoke($destination, $parameters);
};
}
return $destination;
}
/**
* @return mixed
*/
public function interpreter(): mixed
{
return call_user_func($this->pipeline, request());
}
/**
* 设置异常处理器
* @param callable $handler
* @return $this
*/
public function whenException($handler)
{
$this->exceptionHandler = $handler;
return $this;
}
/**
* @return \Closure
*/
protected function carry(): Closure
{
return static function ($stack, $pipe) {
return static function ($passable) use ($stack, $pipe) {
if ($pipe instanceof MiddlewareInterface) {
$pipe = [$pipe, 'OnHandler'];
}
return $pipe($passable, $stack);
};
};
}
/**
* 异常处理
* @param $passable
* @param $e
* @return mixed
* @throws \Throwable
*/
protected function handleException($passable, Throwable $e)
{
if ($this->exceptionHandler) {
return call_user_func($this->exceptionHandler, $passable, $e);
}
throw $e;
}
}