From 4e3b41331d4758bfe44d0b475526761869c4149a Mon Sep 17 00:00:00 2001 From: "as2252258@163.com" Date: Tue, 27 Jul 2021 03:30:55 +0800 Subject: [PATCH] modify --- Annotation/Annotation.php | 9 +- Annotation/Loader.php | 150 +----- Annotation/Model/Get.php | 2 - Annotation/Route/Interceptor.php | 52 -- Annotation/Route/Limits.php | 52 -- Annotation/Route/Middleware.php | 59 +-- Annotation/Route/Route.php | 61 +-- HttpServer/Route/Middlewares.php | 69 +++ HttpServer/Route/Node.php | 808 +++++++++++-------------------- HttpServer/Route/Reduce.php | 46 +- HttpServer/Route/Router.php | 23 +- Server/Worker/ServerWorker.php | 5 - System/Di/Container.php | 751 ++++++++++++++++------------ 13 files changed, 888 insertions(+), 1199 deletions(-) delete mode 100644 Annotation/Route/Interceptor.php delete mode 100644 Annotation/Route/Limits.php create mode 100644 HttpServer/Route/Middlewares.php diff --git a/Annotation/Annotation.php b/Annotation/Annotation.php index 3d175763..8122ce86 100644 --- a/Annotation/Annotation.php +++ b/Annotation/Annotation.php @@ -192,14 +192,9 @@ class Annotation extends Component * @param string|array $outPath * @throws Exception */ - public function runtime(string $dir, string|array $outPath = '') + public function runtime(string $dir) { - if (empty($outPath)) { - $outPath = []; - } else if (is_string($outPath)) { - $outPath = [$outPath]; - } - $this->_loader->loadByDirectory($dir, $outPath); + return $this->_loader->loadByDirectory($dir); } diff --git a/Annotation/Loader.php b/Annotation/Loader.php index 2770c5c7..81153c48 100644 --- a/Annotation/Loader.php +++ b/Annotation/Loader.php @@ -38,13 +38,6 @@ class Loader extends BaseObject private static array $_methods = []; - /** - * @return array - */ - public function getDirectory(): array - { - return static::$_directory; - } /** * @param $path @@ -56,16 +49,6 @@ class Loader extends BaseObject $this->_scanDir(new DirectoryIterator($path), $namespace); } - - /** - * @return array - */ - public function getClasses(): array - { - return static::$_classes; - } - - /** * @param string $class * @param string $property @@ -121,16 +104,6 @@ class Loader extends BaseObject } - /** - * @param string $class - * @return array - */ - public function getTarget(string $class): array - { - return static::$_classes[$class] ?? []; - } - - /** * @param DirectoryIterator $paths * @param $namespace @@ -173,16 +146,7 @@ class Loader extends BaseObject } $this->appendFileToDirectory($path->getRealPath(), $replace->getName()); - $_array['handler'] = $replace->newInstance(); - $_array['target'] = []; - $_array['methods'] = []; - $_array['property'] = []; - - $_array = $this->_targets($replace, $_array); - $_array = $this->_methods($replace, $_array); - $_array = $this->_properties($replace, $_array); - - static::$_classes[$replace->getName()] = $_array; + static::$_classes[] = $replace->getName(); } catch (Throwable $throwable) { $this->addError($throwable, 'throwable'); } @@ -202,75 +166,6 @@ class Loader extends BaseObject } - /** - * @param ReflectionClass $replace - * @param array $_array - * @return array - */ - private function _targets(ReflectionClass $replace, array $_array): array - { - foreach ($replace->getAttributes() as $attribute) { - if ($attribute->getName() == Attribute::class) { - continue; - } - if ($attribute->getName() == Target::class) { - continue; - } - $_array['target'][] = $attribute->newInstance(); - } - return $_array; - } - - - /** - * @param ReflectionClass $replace - * @param array $_array - * @return array - */ - private function _methods(ReflectionClass $replace, array $_array): array - { - $methods = $replace->getMethods(ReflectionMethod::IS_PUBLIC); - foreach ($methods as $method) { - $_method = []; - foreach ($method->getAttributes() as $attribute) { - if (!class_exists($attribute->getName())) { - continue; - } - $_method[] = $attribute->newInstance(); - } - if (!empty($_method)) { - static::$_methods[$replace->getName()][$method->getName()] = $_method; - } - } - return $_array; - } - - - /** - * @param ReflectionClass $replace - * @param array $_array - * @return array - */ - private function _properties(ReflectionClass $replace, array $_array): array - { - $methods = $replace->getProperties(); - foreach ($methods as $method) { - $_property = []; - if ($method->isStatic()) continue; - foreach ($method->getAttributes() as $attribute) { - if (!class_exists($attribute->getName())) { - continue; - } - $_property[] = $attribute->newInstance(); - } - if (!empty($_property)) { - static::$_property[$replace->getName()][$method->getName()] = $_property; - } - } - return $_array; - } - - /** * @param string $path * @param string|array $outPath @@ -280,15 +175,22 @@ class Loader extends BaseObject { try { $path = '/' . trim($path, '/'); + + $paths = []; foreach (static::$_directory as $key => $_path) { $key = '/' . trim($key, '/'); if (!str_starts_with($key, $path) || in_array($key, $outPath)) { continue; } - $this->execute($_path); + + foreach ($_path as $item) { + $paths[] = $item; + } } + return $paths; } catch (Throwable $exception) { $this->addError($exception, 'throwable'); + return []; } } @@ -326,38 +228,4 @@ class Loader extends BaseObject } - /** - * @param array $classes - * @throws Exception - */ - private function execute(array $classes) - { - if (empty($classes)) { - return; - } - foreach ($classes as $className) { - if (!isset(static::$_methods[$className])) { - continue; - } - foreach (static::$_methods[$className] as $name => $attribute) { - $this->methods($attribute, $className, $name); - } - } - } - - - /** - * @param $attribute - * @param $annotation - * @param $className - * @param $name - */ - private function methods($attribute, $className, $name) - { - $handler = static::$_classes[$className]['handler']; - foreach ($attribute as $value) { - $value->execute($handler, $name); - } - } - } diff --git a/Annotation/Model/Get.php b/Annotation/Model/Get.php index e10f4257..77592126 100644 --- a/Annotation/Model/Get.php +++ b/Annotation/Model/Get.php @@ -4,9 +4,7 @@ namespace Annotation\Model; -use Annotation\Annotation; use Attribute; -use Database\ActiveRecord; use Exception; use Snowflake\Snowflake; diff --git a/Annotation/Route/Interceptor.php b/Annotation/Route/Interceptor.php deleted file mode 100644 index c7974696..00000000 --- a/Annotation/Route/Interceptor.php +++ /dev/null @@ -1,52 +0,0 @@ -interceptor)) { - $this->interceptor = [$this->interceptor]; - } - - foreach ($this->interceptor as $key => $value) { - $sn = Snowflake::createObject($value); - - if (!($sn instanceof \HttpServer\IInterface\Interceptor)) { - continue; - } - - $this->interceptor[$key] = [$sn, 'Interceptor']; - } - } - - - /** - * @param mixed $class - * @param mixed|null $method - * @return Interceptor - */ - public function execute(mixed $class, mixed $method = null): static - { - return $this; - } - -} diff --git a/Annotation/Route/Limits.php b/Annotation/Route/Limits.php deleted file mode 100644 index f9f1ac94..00000000 --- a/Annotation/Route/Limits.php +++ /dev/null @@ -1,52 +0,0 @@ -limits)) { - $this->limits = [$this->limits]; - } - - foreach ($this->limits as $key => $value) { - $sn = Snowflake::createObject($value); - - if (!($sn instanceof \HttpServer\IInterface\Limits)) { - continue; - } - - $this->limits[$key] = [$sn, 'next']; - } - } - - - /** - * @param mixed $class - * @param mixed|null $method - * @return Limits - */ - public function execute(mixed $class, mixed $method = null): static - { - return $this; - } - - -} diff --git a/Annotation/Route/Middleware.php b/Annotation/Route/Middleware.php index 0395e321..87113ad4 100644 --- a/Annotation/Route/Middleware.php +++ b/Annotation/Route/Middleware.php @@ -5,6 +5,7 @@ namespace Annotation\Route; use Annotation\Attribute; +use HttpServer\Route\Middlewares; use Snowflake\Snowflake; use HttpServer\IInterface\Middleware as IMiddleware; @@ -16,38 +17,40 @@ use HttpServer\IInterface\Middleware as IMiddleware; { - /** - * Interceptor constructor. - * @param string|array $middleware - * @throws - */ - public function __construct(public string|array $middleware) - { - if (is_string($this->middleware)) { - $this->middleware = [$this->middleware]; - } + /** + * Interceptor constructor. + * @param string|array $middleware + * @throws + */ + public function __construct(public string|array $middleware) + { + if (is_string($this->middleware)) { + $this->middleware = [$this->middleware]; + } - $array = []; - foreach ($this->middleware as $key => $value) { - $sn = Snowflake::createObject($value); - if (!($sn instanceof IMiddleware)) { - continue; - } - $array[] = [$sn, 'onHandler']; - } - $this->middleware = $array; - } + $array = []; + foreach ($this->middleware as $value) { + $sn = Snowflake::createObject($value); + if (!($sn instanceof IMiddleware)) { + continue; + } + $array[] = [$sn, 'onHandler']; + } + $this->middleware = $array; + } - /** - * @param mixed $class - * @param mixed|null $method - * @return Middleware - */ + /** + * @param mixed $class + * @param mixed|null $method + * @return Middleware + */ public function execute(mixed $class, mixed $method = null): static - { - return $this; - } + { + $middleware = Snowflake::getDi()->get(Middlewares::class); + $middleware->addMiddlewares($class, $method, $this->middleware); + return $this; + } } diff --git a/Annotation/Route/Route.php b/Annotation/Route/Route.php index 4c48bdc9..be7c2fa3 100644 --- a/Annotation/Route/Route.php +++ b/Annotation/Route/Route.php @@ -13,36 +13,43 @@ use Snowflake\Snowflake; #[\Attribute(\Attribute::TARGET_METHOD)] class Route extends Attribute { - /** - * Route constructor. - * @param string $uri - * @param string $method - * @param string $version - */ - public function __construct( - public string $uri, - public string $method, - public string $version = 'v.1.0' - ) - { - } + /** + * Route constructor. + * @param string $uri + * @param string $method + * @param string $version + */ + public function __construct( + public string $uri, + public string $method, + public string $version = 'v.1.0' + ) + { + } - /** - * @param mixed $class - * @param mixed|null $method - * @return Router - * @throws Exception - */ + /** + * @param mixed $class + * @param mixed|null $method + * @return Router + * @throws Exception + */ public function execute(mixed $class, mixed $method = null): Router - { - // TODO: Implement setHandler() method. - $router = Snowflake::app()->getRouter(); - - $router->addRoute($this->uri, [$class, $method], $this->method); - - return $router; - } + { + // TODO: Implement setHandler() method. + $router = Snowflake::app()->getRouter(); + $node = $router->addRoute($this->uri, [$class, $method], $this->method); + if ($node !== null) { + $attribute = Snowflake::getDi()->getMethodAttribute($class::class, $method); + foreach ($attribute as $item) { + if ($item instanceof Route) { + continue; + } + $item->execute($class, $method); + } + } + return $router; + } } diff --git a/HttpServer/Route/Middlewares.php b/HttpServer/Route/Middlewares.php new file mode 100644 index 00000000..ceb4bdd1 --- /dev/null +++ b/HttpServer/Route/Middlewares.php @@ -0,0 +1,69 @@ +onHandler($passable, $stack); + } + return call_user_func($pipe, $passable, $stack); + }; + }, $caller); + } + +} diff --git a/HttpServer/Route/Node.php b/HttpServer/Route/Node.php index 56f572fa..75a3daee 100644 --- a/HttpServer/Route/Node.php +++ b/HttpServer/Route/Node.php @@ -5,15 +5,10 @@ declare(strict_types=1); namespace HttpServer\Route; -use Annotation\Route\After; -use Annotation\Route\Interceptor; -use Annotation\Route\Limits; -use Annotation\Route\Middleware; use Annotation\Route\RpcProducer; use Closure; use Exception; use HttpServer\Abstracts\HttpService; -use HttpServer\Controller; use HttpServer\Http\Context; use HttpServer\Http\Request; use JetBrains\PhpStorm\Pure; @@ -22,7 +17,6 @@ use Snowflake\Aop; use Snowflake\Core\Json; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; -use Throwable; /** * Class Node @@ -31,524 +25,288 @@ use Throwable; class Node extends HttpService { - public string $path = ''; - public int $index = 0; - public string $method = ''; - - /** @var Node[] $childes */ - public array $childes = []; - - public array $group = []; - - private string $_error = ''; - - private string $_dataType = ''; - - /** @var ?Closure|?array */ - public Closure|array|null $handler; - public string $htmlSuffix = '.html'; - public bool $enableHtmlSuffix = false; - public array $namespace = []; - public array $middleware = []; - - /** @var array|Closure */ - public Closure|array $callback = []; - - private string $_alias = ''; - - private array $_interceptors = []; - private array $_after = []; - private array $_limits = []; - - - /** - * @param string $dataType - */ - public function setDataType(string $dataType) - { - $this->_dataType = $dataType; - } - - - /** - * @param string $data - * @return mixed - */ - public function unpack(string $data): mixed - { - if ($this->_dataType == RpcProducer::PROTOCOL_JSON) { - return json_decode($data, true); - } - if ($this->_dataType == RpcProducer::PROTOCOL_SERIALIZE) { - return unserialize($data); - } - return $data; - } - - - /** - * @param $handler - * @return Node - * @throws - */ - public function bindHandler($handler): static - { - if (is_string($handler) && str_contains($handler, '@')) { - list($controller, $action) = explode('@', $handler); - if (!class_exists($controller) && !empty($this->namespace)) { - $controller = implode('\\', $this->namespace) . '\\' . $controller; - } - $this->handler = $this->getReflect($controller, $action); - } else if ($handler != null && !is_callable($handler, true)) { - $this->_error = 'Controller is con\'t exec.'; - } else if ($handler instanceof Closure) { - $this->handler = $handler; - } else { - [$controller, $action] = $this->handler = $handler; - if (!($controller instanceof Controller)) { - return $this; - } - $this->annotationInject($controller::class, $action); - } - if (!empty($this->handler)) { - $this->callback = Reduce::reduce($this->createDispatch(), $this->annotation()); - $this->setAop(); - } - return $this; - } - - private array $_aop; - - - /** - * @return Closure - * @throws Exception - */ - public function createDispatch(): Closure - { - $application = $this; - return static function () use ($application) { - $dispatchParam = Context::getContext('dispatch-param', [\request()]); - if (!empty($application->_aop)) { - return call_user_func($application->_aop[0], $application->_aop[1], $dispatchParam); - } - return call_user_func($application->handler, ...$dispatchParam); - }; - } - - - /** - * @throws ReflectionException - * @throws NotFindClassException - * @throws Exception - */ - private function setAop() - { - /** @var Aop $aop */ - $aop = Snowflake::app()->get('aop'); - if (!is_array($this->handler) || !$aop->hasAop($this->handler)) { - return; - } - $reflect = $aop->getAop($this->handler); - $this->_aop = [ - [$reflect->getMethod('invoke'), 'invokeArgs'], - $reflect->newInstance($this->handler) - ]; - } - - - private bool $_hasBeforeAction = false; - - - /** - * @return bool - * @throws Exception - */ - public function beforeAction(): bool - { - if (!$this->_hasBeforeAction) return true; - [$controller, $action] = $this->handler; - if (!$controller->beforeAction(\request())) { - return false; - } - return true; - } - - - /** - * @return array - */ - #[Pure] protected function annotation(): array - { - $middleWares = $this->getMiddleWares(); - $middleWares = $this->annotation_limit($this, $middleWares); - return $this->annotation_interceptor($this, $middleWares); - } - - - /** - * @param Node $node - * @param array $middleWares - * @return array - */ - #[Pure] protected function annotation_interceptor(Node $node, array $middleWares = []): array - { - if (!$node->hasInterceptor()) { - return $middleWares; - } - foreach ($node->getInterceptor() as $item) { - $middleWares[] = $item; - } - return $middleWares; - } - - - /** - * @param Node $node - * @param array $middleWares - * @return array - */ - #[Pure] protected function annotation_limit(Node $node, array $middleWares = []): array - { - if (!$node->hasLimits()) { - return $middleWares; - } - foreach ($node->getLimits() as $item) { - $middleWares[] = $item; - } - return $middleWares; - } - - - /** - * @return bool - */ - #[Pure] public function hasInterceptor(): bool - { - return count($this->_interceptors) > 0; - } - - - /** - * @return bool - */ - #[Pure] public function hasLimits(): bool - { - return count($this->_limits) > 0; - } - - - /** - * @param null $response - * @return mixed - * @throws Exception - */ - public function afterDispatch($response = null): mixed - { - if (is_object($this->_after[0])) { - return call_user_func($this->_after, \request(), $response); - } - foreach ($this->_after as $value) { - call_user_func($value, \request(), $response); - } - return $this->_after; - } - - - /** - * @return array - */ - public function getInterceptor(): array - { - return $this->_interceptors; - } - - - /** - * @return array - */ - public function getAfters(): array - { - return $this->_after; - } - - - /** - * @return bool - */ - #[Pure] public function hasAfter(): bool - { - return count($this->_after) > 0; - } - - - /** - * @return array - */ - public function getLimits(): array - { - return $this->_limits; - } - - /** - * @param Request $request - * @return bool - */ - public function methodAllow(Request $request): bool - { - if ($this->method == $request->getMethod()) { - return true; - } - return $this->method == 'any'; - } - - /** - * @return bool - * @throws Exception - */ - public function checkSuffix(): bool - { - if ($this->enableHtmlSuffix) { - $url = request()->getUri(); - $nowLength = strlen($this->htmlSuffix); - if (strpos($url, $this->htmlSuffix) !== strlen($url) - $nowLength) { - return false; - } - } - return true; - } - - - /** - * @param string $controller - * @param string $action - * @return null|array - * @throws Exception - */ - private function getReflect(string $controller, string $action): ?array - { - try { - $reflect = Snowflake::getDi()->getReflect($controller); - if (empty($reflect)) { - throw new Exception($controller . ' Class is con\'t Instantiable.'); - } - if (!empty($action) && !$reflect->hasMethod($action)) { - throw new Exception('method ' . $action . ' not exists at ' . $controller . '.'); - } - - $this->_hasBeforeAction = $reflect->hasMethod('beforeAction'); - - $this->annotationInject($reflect->getName(), $action); - - return [$reflect->newInstance(), $action]; - } catch (Throwable $exception) { - $this->_error = $exception->getMessage(); - $this->addError($exception, 'router'); - return null; - } - } - - - /** - * @param Closure|array|string $handler - * @throws Exception - */ - public function addInterceptor(Closure|string|array $handler) - { - if (!is_array($handler) || is_object($handler[0])) { - $handler = [$handler]; - } - foreach ($handler as $closure) { - if (in_array($closure, $this->_interceptors)) { - continue; - } - $this->_interceptors[] = $closure; - } - } - - - /** - * @param string $className - * @param string $action - * @return Node - * @throws Exception - */ - public function annotationInject(string $className, string $action): Node - { - $annotation = annotation()->getMethods($className, $action); - if (empty($annotation)) { - return $this; - } - foreach ($annotation as $attribute) { - if ($attribute instanceof Interceptor) { - $this->addInterceptor($attribute->interceptor); - } - if ($attribute instanceof After) { - $this->addAfter($attribute->after); - } - if ($attribute instanceof Middleware) { - $this->addMiddleware($attribute->middleware); - } - if ($attribute instanceof Limits) { - $this->addLimits($attribute->limits); - } - } - return $this; - } - - - /** - * @param Closure|array|string $handler - * @throws Exception - */ - public function addAfter(Closure|string|array $handler) - { - if (!is_array($handler) || is_object($handler[0])) { - $handler = [$handler]; - } - foreach ($handler as $closure) { - if (in_array($closure, $this->_after)) { - continue; - } - $this->_after[] = $closure; - } - } - - - /** - * @param Closure|array|string $handler - * @throws Exception - */ - public function addLimits(Closure|string|array $handler) - { - if (!is_array($handler) || is_object($handler[0])) { - $handler = [$handler]; - } - foreach ($handler as $closure) { - if (in_array($closure, $this->_limits)) { - continue; - } - $this->_limits[] = $closure; - } - } - - - /** - * @return string - * 错误信息 - */ - public function getError(): string - { - return $this->_error; - } - - /** - * @param Node $node - * @param string $field - * @return Node - */ - public function addChild(Node $node, string $field): Node - { - $field = (string)$field; - /** @var Node $oLod */ - $oLod = $this->childes[$field] ?? null; - if (!empty($oLod)) { - $node = $oLod; - } - $this->childes[$field] = $node; - return $this->childes[$field]; - } - - - /** - * @param string $search - * @return Node|null - * @throws Exception - */ - public function findNode(string $search): ?Node - { - if (empty($this->childes)) { - return null; - } - if (isset($this->childes[$search])) { - return $this->childes[$search]; - } - foreach ($this->childes as $key => $val) { - if ($search == $key) { - return $this->childes[$key]; - } - } - return null; - } - - - /** - * @param string $alias - * @return $this - * 别称 - */ - public function alias(string $alias): static - { - $this->_alias = $alias; - return $this; - } - - - /** - * @return string - */ - public function getAlias(): string - { - return $this->_alias; - } - - - /** - * @param Closure|array $class - * @return $this - */ - public function addMiddleware(Closure|array $class): static - { - if (empty($class)) return $this; - foreach ($class as $closure) { - if (in_array($closure, $this->middleware)) { - continue; - } - $this->middleware[] = $closure; - } - return $this; - } - - - /** - * @return array - */ - public function getMiddleWares(): array - { - return $this->middleware; - } - - - /** - * @return mixed - * @throws Exception - */ - public function dispatch(): mixed - { - Context::setContext('dispatch-param', func_get_args()); - if (empty($this->callback)) { - return Json::to(404, $this->errorMsg()); - } - return call_user_func($this->callback, \request()); - } - - - /** - * @return string - */ - private function errorMsg(): string - { - return $this->_error ?? 'Page not found.'; - } + public string $path = ''; + public int $index = 0; + public string $method = ''; + + /** @var Node[] $childes */ + public array $childes = []; + + public array $group = []; + + private string $_error = ''; + + private string $_dataType = ''; + + /** @var ?Closure|?array */ + public Closure|array|null $handler; + public string $htmlSuffix = '.html'; + public bool $enableHtmlSuffix = false; + public array $namespace = []; + public array $middleware = []; + + /** @var array|Closure */ + public Closure|array $callback = []; + + private string $_alias = ''; + + + /** + * @param string $dataType + */ + public function setDataType(string $dataType) + { + $this->_dataType = $dataType; + } + + + /** + * @param string $data + * @return mixed + */ + public function unpack(string $data): mixed + { + if ($this->_dataType == RpcProducer::PROTOCOL_JSON) { + return json_decode($data, true); + } + if ($this->_dataType == RpcProducer::PROTOCOL_SERIALIZE) { + return unserialize($data); + } + return $data; + } + + + /** + * @param $handler + * @return Node + * @throws + */ + public function bindHandler($handler): static + { + if (is_string($handler) && str_contains($handler, '@')) { + list($controller, $action) = explode('@', $handler); + if (!class_exists($controller) && !empty($this->namespace)) { + $controller = implode('\\', $this->namespace) . '\\' . $controller; + } + $this->handler = [Snowflake::getDi()->get($controller), $action]; + } else if ($handler != null && !is_callable($handler, true)) { + $this->_error = 'Controller is con\'t exec.'; + } else { + $this->handler = $handler; + } + if (!empty($this->handler)) { + $this->callback = di(Middlewares::class)->callerMiddlewares( + $this->handler[0], $this->handler[1], $this->createDispatch() + ); + } + return $this; + } + + + /** + * @throws ReflectionException + * @throws NotFindClassException + * @throws Exception + */ + private function createDispatch() + { + $application = $this; + + /** @var Aop $aop */ + $aop = Snowflake::app()->get('aop'); + if (!is_array($this->handler) || !$aop->hasAop($this->handler)) { + return static function () use ($application) { + $dispatchParam = Context::getContext('dispatch-param', [\request()]); + + return call_user_func($application->handler, ...$dispatchParam); + }; + } + + $reflect = $aop->getAop($this->handler); + $callback = [$reflect->getMethod('invoke'), 'invokeArgs']; + + return static function () use ($callback, $application, $reflect) { + $dispatchParam = Context::getContext('dispatch-param', [\request()]); + + $asp = $reflect->newInstance($this->handler); + + call_user_func($callback, $asp, $dispatchParam); + }; + } + + + /** + * @return array + */ + #[Pure] protected function annotation(): array + { + return $this->getMiddleWares(); + } + + + /** + * @param Request $request + * @return bool + */ + public function methodAllow(Request $request): bool + { + if ($this->method == $request->getMethod()) { + return true; + } + return $this->method == 'any'; + } + + /** + * @return bool + * @throws Exception + */ + public function checkSuffix(): bool + { + if ($this->enableHtmlSuffix) { + $url = request()->getUri(); + $nowLength = strlen($this->htmlSuffix); + if (strpos($url, $this->htmlSuffix) !== strlen($url) - $nowLength) { + return false; + } + } + return true; + } + + + /** + * @param Closure|array|string $handler + * @throws Exception + */ + public function addLimits(Closure|string|array $handler) + { + if (!is_array($handler) || is_object($handler[0])) { + $handler = [$handler]; + } + foreach ($handler as $closure) { + if (in_array($closure, $this->_limits)) { + continue; + } + $this->_limits[] = $closure; + } + } + + + /** + * @return string + * 错误信息 + */ + public function getError(): string + { + return $this->_error; + } + + /** + * @param Node $node + * @param string $field + * @return Node + */ + public function addChild(Node $node, string $field): Node + { + $field = (string)$field; + /** @var Node $oLod */ + $oLod = $this->childes[$field] ?? null; + if (!empty($oLod)) { + $node = $oLod; + } + $this->childes[$field] = $node; + return $this->childes[$field]; + } + + + /** + * @param string $search + * @return Node|null + * @throws Exception + */ + public function findNode(string $search): ?Node + { + if (empty($this->childes)) { + return null; + } + if (isset($this->childes[$search])) { + return $this->childes[$search]; + } + foreach ($this->childes as $key => $val) { + if ($search == $key) { + return $this->childes[$key]; + } + } + return null; + } + + + /** + * @param string $alias + * @return $this + * 别称 + */ + public function alias(string $alias): static + { + $this->_alias = $alias; + return $this; + } + + + /** + * @return string + */ + public function getAlias(): string + { + return $this->_alias; + } + + + /** + * @param Closure|array $class + * @return $this + */ + public function addMiddleware(Closure|array $class): static + { + if (empty($class)) return $this; + foreach ($class as $closure) { + if (in_array($closure, $this->middleware)) { + continue; + } + $this->middleware[] = $closure; + } + return $this; + } + + + /** + * @return array + */ + public function getMiddleWares(): array + { + return $this->middleware; + } + + + /** + * @return mixed + * @throws Exception + */ + public function dispatch(): mixed + { + Context::setContext('dispatch-param', func_get_args()); + if (empty($this->callback)) { + return Json::to(404, $this->errorMsg()); + } + return call_user_func($this->callback, \request()); + } + + + /** + * @return string + */ + private function errorMsg(): string + { + return $this->_error ?? 'Page not found.'; + } } diff --git a/HttpServer/Route/Reduce.php b/HttpServer/Route/Reduce.php index 2c3147b4..44173d72 100644 --- a/HttpServer/Route/Reduce.php +++ b/HttpServer/Route/Reduce.php @@ -19,52 +19,16 @@ class Reduce * @return mixed */ public static function reduce($last, $middleWares): mixed - { - return array_reduce(array_reverse($middleWares), static::core(), $last); - } - - - /** - * @param $middleWares - * @return mixed - */ - public static function after($middleWares): mixed { return array_reduce(array_reverse($middleWares), function ($stack, $pipe) { - return function ($request, $passable) use ($stack, $pipe) { - if (!($pipe instanceof After)) { - return call_user_func($pipe, $request, $passable, $stack); + return function ($passable) use ($stack, $pipe) { + if ($pipe instanceof Middleware) { + return $pipe->onHandler($passable, $stack); } - return $pipe->onHandler($request, $passable); + return call_user_func($pipe, $passable, $stack); }; - }); + }, $last); } - /** - * @return Closure - */ - private static function core(): Closure - { - return function ($stack, $pipe) { - return static::passable($stack, $pipe); - }; - } - - - /** - * @param $stack - * @param $pipe - * @return Closure - */ - public static function passable($stack, $pipe): Closure - { - return function ($passable) use ($stack, $pipe) { - if ($pipe instanceof Middleware) { - return $pipe->onHandler($passable, $stack); - } - return call_user_func($pipe, $passable, $stack); - }; - } - } diff --git a/HttpServer/Route/Router.php b/HttpServer/Route/Router.php index 623596d1..9573a123 100644 --- a/HttpServer/Route/Router.php +++ b/HttpServer/Route/Router.php @@ -44,6 +44,9 @@ class Router extends HttpService implements RouterInterface public int $useTree = ROUTER_TREE; + private static array $controllers = []; + + public ?Response $response = null; @@ -119,10 +122,6 @@ class Router extends HttpService implements RouterInterface $handler = Closure::bind($handler, new Controller()); } -// if ($this->useTree === ROUTER_TREE) { -// return $this->tree($path, $handler, $method); -// } - return $this->hash($path, $handler, $method); } @@ -136,7 +135,6 @@ class Router extends HttpService implements RouterInterface private function hash($path, $handler, string $method = 'any'): ?Node { $path = $this->resolve($path); - static::$nodes[$method][$path] = $this->NodeInstance($path, 0, $method); return static::$nodes[$method][$path]->bindHandler($handler); @@ -343,11 +341,9 @@ class Router extends HttpService implements RouterInterface if ($this->middleware instanceof \Closure) { $node->addMiddleware([$this->middleware]); } - if (is_array($name)) { $node->addMiddleware($this->resolve_middleware($name)); } - return $node; } @@ -527,10 +523,7 @@ class Router extends HttpService implements RouterInterface $this->response->setFormat(Response::HTML); $this->response->send('

404

'); } else { - $this->response->send(($response = $node->dispatch()), 200); - if ($node->hasAfter()) { - $node->afterDispatch($response); - } + $this->response->send($node->dispatch(), 200); } } @@ -637,6 +630,14 @@ class Router extends HttpService implements RouterInterface public function _loader() { $this->loadRouteDir(APP_PATH . 'routes'); + $classes = Snowflake::getAnnotation()->runtime(CONTROLLER_PATH); + foreach ($classes as $class) { + $instance = Snowflake::getDi()->get($class); + $methods = Snowflake::getDi()->getMethodAttribute($class); + foreach ($methods as $method => $attribute) { + $attribute->execute($instance, $method); + } + } } /** diff --git a/Server/Worker/ServerWorker.php b/Server/Worker/ServerWorker.php index 9904bf55..2cb849a5 100644 --- a/Server/Worker/ServerWorker.php +++ b/Server/Worker/ServerWorker.php @@ -56,15 +56,10 @@ class ServerWorker extends \Server\Abstracts\Server echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Worker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL; $this->setProcessName(sprintf('Worker[%d].%d', $server->worker_pid, $workerId)); - - $annotation->runtime(CONTROLLER_PATH); - $annotation->runtime(MODEL_PATH); } else { echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m Tasker[%d].%d start.", $server->worker_pid, $workerId) . PHP_EOL; $this->setProcessName(sprintf('Tasker[%d].%d', $server->worker_pid, $workerId)); - - $annotation->runtime(APP_PATH, [CONTROLLER_PATH]); } } diff --git a/System/Di/Container.php b/System/Di/Container.php index 37112179..91d10909 100644 --- a/System/Di/Container.php +++ b/System/Di/Container.php @@ -9,13 +9,16 @@ declare(strict_types=1); namespace Snowflake\Di; +use Annotation\Attribute; use Annotation\Inject; +use Annotation\Target; use Exception; use ReflectionClass; use ReflectionException; use ReflectionMethod; use ReflectionProperty; use Snowflake\Abstracts\BaseObject; +use Snowflake\Abstracts\Configure; use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; @@ -26,344 +29,476 @@ use Snowflake\Snowflake; class Container extends BaseObject { - /** - * @var array - * - * instance class by className - */ - private array $_singletons = []; + /** + * @var array + * + * instance class by className + */ + private static array $_singletons = []; - /** - * @var array - * - * class new instance construct parameter - */ - private array $_constructs = []; + /** + * @var array + * + * class new instance construct parameter + */ + private static array $_constructs = []; - /** - * @var array - * - * implements \ReflectClass - */ - private array $_reflection = []; - - private array $_reflectionProperty = []; + /** + * @var array + * + * implements \ReflectClass + */ + private static array $_reflection = []; - private array $_property = []; + /** + * @var ReflectionProperty[] + */ + private static array $_reflectionProperty = []; + + /** + * @var ReflectionMethod[] + */ + private static array $_reflectionMethod = []; + + /** + * @var ReflectionClass[] + */ + private static array $_reflectionClass = []; - /** - * @var array - * - * The construct parameter - */ - private array $_param = []; - - /** - * @param $class - * @param array $constrict - * @param array $config - * - * @return mixed - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - public function get($class, array $constrict = [], array $config = []): mixed - { - if (isset($this->_singletons[$class])) { - return $this->_singletons[$class]; - } else if (!isset($this->_constructs[$class])) { - return $this->resolve($class, $constrict, $config); - } - - $definition = $this->_constructs[$class]; - if (is_callable($definition, TRUE)) { - return call_user_func($definition, $this, $constrict, $config); - } else if (is_array($definition)) { - $object = $this->resolveDefinition($definition, $class, $config, $constrict); - } else if (is_object($definition)) { - return $this->_singletons[$class] = $definition; - } else { - throw new NotFindClassException($class); - } - return $this->_singletons[$class] = $object; - } + /** + * @var array + */ + private static array $_propertyAttributes = []; - /** - * @param $definition - * @param $class - * @param $config - * @param $constrict - * @return mixed - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - private function resolveDefinition($definition, $class, $config, $constrict): mixed - { - if (!isset($definition['class'])) { - throw new NotFindClassException($class); - } - $_className = $definition['class']; - unset($definition['class']); + /** + * @var array + */ + private static array $_methodsAttributes = []; + + + /** + * @var array + */ + private static array $_targetAttributes = []; + + + private static array $_attributeMaping = []; + + + /** + * @var array + * + * The construct parameter + */ + private static array $_param = []; + + /** + * @param $class + * @param array $constrict + * @param array $config + * + * @return mixed + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + public function get($class, array $constrict = [], array $config = []): mixed + { + if (isset(static::$_singletons[$class])) { + return static::$_singletons[$class]; + } else if (!isset(static::$_constructs[$class])) { + return $this->resolve($class, $constrict, $config); + } + + $definition = static::$_constructs[$class]; + if (is_callable($definition, TRUE)) { + return call_user_func($definition, $this, $constrict, $config); + } else if (is_array($definition)) { + $object = $this->resolveDefinition($definition, $class, $config, $constrict); + } else if (is_object($definition)) { + return static::$_singletons[$class] = $definition; + } else { + throw new NotFindClassException($class); + } + return static::$_singletons[$class] = $object; + } + + + /** + * @param $definition + * @param $class + * @param $config + * @param $constrict + * @return mixed + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + private function resolveDefinition($definition, $class, $config, $constrict): mixed + { + if (!isset($definition['class'])) { + throw new NotFindClassException($class); + } + $_className = $definition['class']; + unset($definition['class']); // $config = array_merge($definition, $config); - $definition = $this->mergeParam($class, $constrict); + $definition = $this->mergeParam($class, $constrict); - if ($_className === $class) { - $object = $this->resolve($class, $definition, $config); - } else { - $object = $this->get($class, $definition, $config); - } - return $object; - } + if ($_className === $class) { + $object = $this->resolve($class, $definition, $config); + } else { + $object = $this->get($class, $definition, $config); + } + return $object; + } - /** - * @param $class - * @param $constrict - * @param $config - * - * @return object - * @throws Exception - */ - private function resolve($class, $constrict, $config): object - { - /** @var ReflectionClass $reflect */ - [$reflect, $dependencies] = $this->resolveDependencies($class); - if (empty($reflect)) { - throw new NotFindClassException($class); - } - foreach ($constrict as $index => $param) { - $dependencies[$index] = $param; - } + /** + * @param $class + * @param $constrict + * @param $config + * + * @return object + * @throws Exception + */ + private function resolve($class, $constrict, $config): object + { + /** @var ReflectionClass $reflect */ + [$reflect, $dependencies] = $this->resolveDependencies($class); + if (empty($reflect) || !$reflect->isInstantiable()) { + throw new NotFindClassException($class); + } + $dependencies = array_merge($dependencies, $constrict); + unset($dependencies['class']); + if (empty($config) || !is_array($config)) { + $object = $this->newInstance($reflect, $dependencies); + } else if (!empty($dependencies) && $reflect->implementsInterface(Configure::class)) { + $dependencies[count($dependencies) - 1] = $config; + $object = $this->newInstance($reflect, $dependencies); + } else { + if (!empty($config)) static::$_param[$class] = $config; - if (!$reflect->isInstantiable()) { - throw new NotFindClassException($reflect->getName()); - } - - unset($dependencies['class']); - if (empty($config) || !is_array($config)) { - $object = $this->newInstance($reflect, $dependencies); - } else if (!empty($dependencies) && $reflect->implementsInterface('Snowflake\Abstracts\Configure')) { - $dependencies[count($dependencies) - 1] = $config; - $object = $this->newInstance($reflect, $dependencies); - } else { - if (!empty($config)) $this->_param[$class] = $config; - - $object = $this->onAfterInit($this->newInstance($reflect, $dependencies), $config); - } - return $this->propertyInject($reflect, $object); - } + $object = $this->onAfterInit($this->newInstance($reflect, $dependencies), $config); + } + static::$_reflectionClass[$reflect->getName()] = []; + foreach ($reflect->getAttributes() as $attribute) { + static::$_reflectionClass[$reflect->getName()][] = $attribute->newInstance(); + } + return $this->propertyInject($reflect, $object); + } - /** - * @param $reflect - * @param $dependencies - * @return mixed - */ - private function newInstance($reflect, $dependencies): mixed - { - if (!empty($dependencies)) { - return $reflect->newInstanceArgs($dependencies); - } - return $reflect->newInstance(); - } + /** + * @param $reflect + * @param $dependencies + * @return mixed + */ + private function newInstance($reflect, $dependencies): mixed + { + if (!empty($dependencies)) { + return $reflect->newInstanceArgs($dependencies); + } + return $reflect->newInstance(); + } - /** - * @param ReflectionClass $reflect - * @param $object - * @return mixed - * @throws Exception - */ - private function propertyInject(ReflectionClass $reflect, $object): mixed - { - if (!isset($this->_property[$reflect->getName()])) { - return $object; - } - foreach ($this->_property[$reflect->getName()] as $property => $inject) { - /** @var Inject $inject */ - $inject->execute($object, $property); - } - return $object; - } + /** + * @param ReflectionClass $reflect + * @param $object + * @return mixed + * @throws Exception + */ + private function propertyInject(ReflectionClass $reflect, $object): mixed + { + if (!isset(static::$_propertyAttributes[$reflect->getName()])) { + return $object; + } + foreach (static::$_propertyAttributes[$reflect->getName()] as $property => $inject) { + /** @var Inject $inject */ + $inject->execute($object, $property); + } + return $object; + } - /** - * @param string $class - * @param string|null $property - * @return ReflectionProperty|array|null - */ - public function getClassProperty(string $class, string $property = null): ReflectionProperty|null|array - { - if (!isset($this->_reflectionProperty[$class])) { - return null; - } - $properties = $this->_reflectionProperty[$class]; - if (!empty($property)) { - return $properties[$property] ?? null; - } - return $properties; - } + /** + * @param \ReflectionClass $class + */ + private function resolveMethodAttribute(ReflectionClass $class) + { + if ($class->isAbstract() || $class->isTrait()) { + return; + } + foreach ($class->getMethods() as $method) { + if ($method->isStatic()) { + continue; + } + static::$_reflectionMethod[$class->getName()][$method->getName()] = $method; + static::$_methodsAttributes[$class->getName()][$method->getName()] = []; + foreach ($method->getAttributes() as $attribute) { + if (!class_exists($attribute->getName())) { + continue; + } - /** - * @param $object - * @param $config - * @return mixed - */ - private function onAfterInit($object, $config): mixed - { - Snowflake::configure($object, $config); - if (method_exists($object, 'afterInit')) { - call_user_func([$object, 'afterInit']); - } - return $object; - } + $instance = $attribute->newInstance(); - /** - * @param $class - * @return array|null - * @throws ReflectionException|NotFindClassException - */ - private function resolveDependencies($class): ?array - { - if (!isset($this->_reflection[$class])) { - $this->_reflection[$class] = new ReflectionClass($class); - if (!$this->_reflection[$class]->isInstantiable()) { - return null; - } - $this->scanProperty($this->_reflection[$class]); - } - if (!is_null($constructs = $this->_reflection[$class]->getConstructor())) { - $constructs = $this->resolveMethodParam($constructs); - } - return [$this->_reflection[$class], $constructs]; - } + $this->setAttributeMapping($attribute, $class, $method, $instance); + $this->setMethodsAttributes($class, $method, $instance); + static::$_methodsAttributes[$class->getName()][$method->getName()][] = $attribute->newInstance(); + } + } + } - /** - * @param ReflectionClass $reflectionClass - * @return void - */ - private function scanProperty(ReflectionClass $reflectionClass): void - { - $properties = $reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC | - ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED - ); - - $className = $reflectionClass->getName(); - foreach ($properties as $property) { - $targets = $property->getAttributes(Inject::class); - if (count($targets) < 1) { - continue; - } - - $this->_reflectionProperty[$className][$property->getName()] = $property; - - $this->_property[$className][$property->getName()] = $targets[0]->newInstance(); - } - } + /** + * @param \ReflectionAttribute $attribute + * @param \ReflectionClass $class + * @param $object + */ + private function setAttributeMapping(\ReflectionAttribute $attribute, ReflectionClass $class, $object) + { + if (!isset(static::$_attributeMaping[$attribute->getName()])) { + static::$_attributeMaping[$attribute->getName()] = []; + } + static::$_attributeMaping[$attribute->getName()][$class->getName()][] = $object; + } - /** - * @param ReflectionMethod|null $method - * @return array - * @throws NotFindClassException - * @throws ReflectionException - */ - private function resolveMethodParam(?ReflectionMethod $method): array - { - $array = []; - foreach ($method->getParameters() as $key => $parameter) { - if ($parameter->isDefaultValueAvailable()) { - $array[] = $parameter->getDefaultValue(); - } else { - $type = $parameter->getType(); - if (is_string($type) && class_exists($type)) { - $type = Snowflake::createObject($type); - } - $array[] = match ($parameter->getType()) { - 'string' => '', - 'int', 'float' => 0, - '', null, 'object', 'mixed' => NULL, - 'bool' => false, - default => $type - }; - } - } - return $array; - } + /** + * @param \ReflectionAttribute $attribute + * @param \ReflectionClass $class + * @param $object + */ + private function setMethodsAttributes(\ReflectionClass $attribute, ReflectionMethod $method, $object) + { + if (!isset(static::$_methodsAttributes[$attribute->getName()])) { + static::$_methodsAttributes[$attribute->getName()] = []; + } + static::$_methodsAttributes[$attribute->getName()][$method->getName()][] = $object; + } - /** - * @param $class - * @return ReflectionClass|null - * @throws NotFindClassException - * @throws ReflectionException - */ - public function getReflect($class): ?ReflectionClass - { - $reflect = $this->_reflection[$class] ?? null; - if (!is_null($reflect)) { - return $reflect; - } - $reflect = $this->resolveDependencies($class); - if (is_array($reflect)) { - return $reflect[0]; - } - return null; - } + /** + * @param \ReflectionClass $class + */ + private function resolveTargetAttribute(ReflectionClass $class) + { + if ($class->isAbstract() || $class->isTrait()) { + return; + } + foreach ($class->getAttributes() as $method) { + if ($method->getName() == Target::class) { + continue; + } + static::$_targetAttributes[$class->getName()] = $method->newInstance(); + } + } - /** - * @param $class - */ - public function unset($class) - { - if (is_array($class) && isset($class['class'])) { - $class = $class['class']; - } else if (is_object($class)) { - $class = $class::class; - } - unset( - $this->_reflection[$class], $this->_singletons[$class], - $this->_param[$class], $this->_constructs[$class] - ); - } - /** - * @return $this - */ - public function flush(): static - { - $this->_reflection = []; - $this->_singletons = []; - $this->_param = []; - $this->_constructs = []; - return $this; - } + /** + * @param $className + * @param $method + * @return \ReflectionMethod|null + */ + public function getReflectionMethod($className, $method): ?ReflectionMethod + { + return static::$_reflectionMethod[$className][$method] ?? null; + } - /** - * @param $class - * @param $newParam - * - * @return mixed - */ - private function mergeParam($class, $newParam): array - { - if (empty($this->_param[$class])) { - return $newParam; - } else if (empty($newParam)) { - return $this->_param[$class]; - } - $old = $this->_param[$class]; - foreach ($newParam as $key => $val) { - $old[$key] = $val; - } - return $old; - } + + /** + * @param $className + * @param $method + * @return array + */ + public function getMethodAttribute($className, $method = null): array + { + $methods = static::$_methodsAttributes[$className] ?? []; + if ($method === null || empty($method)) { + return $methods; + } + return $methods[$method] ?? []; + } + + + /** + * @param string $class + * @param string|null $property + * @return ReflectionProperty|array|null + */ + public function getClassProperty(string $class, string $property = null): ReflectionProperty|null|array + { + if (!isset(static::$_reflectionProperty[$class])) { + return null; + } + $properties = static::$_reflectionProperty[$class]; + if (!empty($property)) { + return $properties[$property] ?? null; + } + return $properties; + } + + + /** + * @param $object + * @param $config + * @return mixed + */ + private function onAfterInit($object, $config): mixed + { + Snowflake::configure($object, $config); + if (method_exists($object, 'afterInit')) { + call_user_func([$object, 'afterInit']); + } + return $object; + } + + /** + * @param $class + * @return array|null + * @throws ReflectionException|NotFindClassException + */ + private function resolveDependencies($class): ?array + { + if (!isset(static::$_reflection[$class])) { + static::$_reflection[$class] = new ReflectionClass($class); + if (!static::$_reflection[$class]->isInstantiable()) { + return null; + } + $this->resolveTargetAttribute(static::$_reflection[$class]); + $this->resolveMethodAttribute(static::$_reflection[$class]); + $this->scanProperty(static::$_reflection[$class]); + } + if (!is_null($constructs = static::$_reflection[$class]->getConstructor())) { + $constructs = $this->resolveMethodParam($constructs); + } + return [static::$_reflection[$class], $constructs]; + } + + + /** + * @param ReflectionClass $reflectionClass + * @return void + */ + private function scanProperty(ReflectionClass $reflectionClass): void + { + $properties = $reflectionClass->getProperties(ReflectionProperty::IS_PUBLIC | + ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED + ); + + $className = $reflectionClass->getName(); + foreach ($properties as $property) { + $targets = $property->getAttributes(Inject::class); + if (count($targets) < 1) { + continue; + } + + static::$_reflectionProperty[$className][$property->getName()] = $property; + + static::$_propertyAttributes[$className][$property->getName()] = $targets[0]->newInstance(); + } + } + + + /** + * @param ReflectionMethod|null $method + * @return array + * @throws NotFindClassException + * @throws ReflectionException + */ + private function resolveMethodParam(?ReflectionMethod $method): array + { + $array = []; + foreach ($method->getParameters() as $key => $parameter) { + if ($parameter->isDefaultValueAvailable()) { + $array[] = $parameter->getDefaultValue(); + } else { + $type = $parameter->getType(); + if (is_string($type) && class_exists($type)) { + $type = Snowflake::createObject($type); + } + $array[] = match ($parameter->getType()) { + 'string' => '', + 'int', 'float' => 0, + '', null, 'object', 'mixed' => NULL, + 'bool' => false, + default => $type + }; + } + } + return $array; + } + + + /** + * @param $class + * @return ReflectionClass|null + * @throws NotFindClassException + * @throws ReflectionException + */ + public function getReflect($class): ?ReflectionClass + { + $reflect = static::$_reflection[$class] ?? null; + if (!is_null($reflect)) { + return $reflect; + } + $reflect = $this->resolveDependencies($class); + if (is_array($reflect)) { + return $reflect[0]; + } + return null; + } + + /** + * @param $class + */ + public function unset($class) + { + if (is_array($class) && isset($class['class'])) { + $class = $class['class']; + } else if (is_object($class)) { + $class = $class::class; + } + unset( + static::$_reflection[$class], static::$_singletons[$class], + static::$_param[$class], static::$_constructs[$class] + ); + } + + /** + * @return $this + */ + public function flush(): static + { + static::$_reflection = []; + static::$_singletons = []; + static::$_param = []; + static::$_constructs = []; + return $this; + } + + /** + * @param $class + * @param $newParam + * + * @return mixed + */ + private function mergeParam($class, $newParam): array + { + if (empty(static::$_param[$class])) { + return $newParam; + } else if (empty($newParam)) { + return static::$_param[$class]; + } + $old = static::$_param[$class]; + foreach ($newParam as $key => $val) { + $old[$key] = $val; + } + return $old; + } }