111
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user