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
* @return mixed
*/
public static function get($path, $method): mixed
public static function get($path, $method): ?Pipeline
{
return static::$handlers[$method][$path] ?? null;
}
+98 -77
View File
@@ -16,91 +16,112 @@ use Kiri\Abstracts\BaseObject;
class MiddlewareManager extends BaseObject
{
private static array $_middlewares = [];
private static array $_middlewares = [];
/**
* @param $class
* @param $method
* @param array|string $middlewares
*/
public static function addMiddlewares($class, $method, array|string $middlewares)
{
if (is_object($class)) {
$class = $class::class;
}
if (!isset(static::$_middlewares[$class . '::' . $method])) {
static::$_middlewares[$class . '::' . $method] = [];
}
/**
* @param $class
* @param $method
* @param array|string $middlewares
*/
public static function addMiddlewares($class, $method, array|string $middlewares)
{
if (is_object($class)) {
$class = $class::class;
}
if (!isset(static::$_middlewares[$class . '::' . $method])) {
static::$_middlewares[$class . '::' . $method] = [];
}
if (is_string($middlewares) && !in_array($middlewares, static::$_middlewares[$class . '::' . $method])) {
static::$_middlewares[$class . '::' . $method][] = $middlewares;
return;
}
foreach ($middlewares as $middleware) {
if (in_array($middleware, static::$_middlewares[$class . '::' . $method])) {
continue;
}
static::$_middlewares[$class . '::' . $method][] = $middleware;
}
}
if (is_string($middlewares) && !in_array($middlewares, static::$_middlewares[$class . '::' . $method])) {
static::$_middlewares[$class . '::' . $method][] = $middlewares;
return;
}
foreach ($middlewares as $middleware) {
if (in_array($middleware, static::$_middlewares[$class . '::' . $method])) {
continue;
}
static::$_middlewares[$class . '::' . $method][] = $middleware;
}
}
/**
* @param $class
* @param $method
* @return bool
*/
public static function hasMiddleware($class, $method): bool
{
if (is_object($class)) {
$class = $class::class;
}
return isset(static::$_middlewares[$class . '::' . $method]);
}
/**
* @param $handler
* @return mixed|null
*/
public static function get($handler)
{
if ($handler instanceof Closure) {
return null;
}
[$class, $method] = [$handler[0]::class, $handler[1]];
if (!static::hasMiddleware($class, $method)) {
return null;
}
return static::$_middlewares[$class . '::' . $method];
}
/**
* @param $class
* @param $method
* @param $caller
* @return mixed
*/
public static function callerMiddlewares($class, $method, $caller): mixed
{
if (is_object($class)) {
$class = $class::class;
}
$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 $class
* @param $method
* @return bool
*/
public static function hasMiddleware($class, $method): bool
{
if (is_object($class)) {
$class = $class::class;
}
return isset(static::$_middlewares[$class . '::' . $method]);
}
/**
* @param $middlewares
* @param Closure $caller
* @return Closure
*/
public static function closureMiddlewares($middlewares, Closure $caller): Closure
{
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 $class
* @param $method
* @param $caller
* @return mixed
*/
public static function callerMiddlewares($class, $method, $caller): mixed
{
if (is_object($class)) {
$class = $class::class;
}
$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) {
$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
{
if (!($handler instanceof Closure)) {
$callback = $this->injectControllerMiddleware($method, $handler, $_injectParameters);
} else {
$callback = $this->injectClosureMiddleware($method, $handler, $_injectParameters);
}
$callback = (new Pipeline())->overall($this->router->getMiddleware())
->through($this->middleware[$method] ?? [])
->through(MiddlewareManager::get($handler))
->send($_injectParameters)
->then($handler);
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 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
*/
@@ -427,7 +329,7 @@ class Node
if (empty($handlerProviders)) {
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;
}
}