diff --git a/Annotation/Inject.php b/Annotation/Inject.php index 7ebd64d2..4b86aab8 100644 --- a/Annotation/Inject.php +++ b/Annotation/Inject.php @@ -5,6 +5,7 @@ namespace Annotation; use Exception; +use HttpServer\Http\Context; use ReflectionException; use ReflectionProperty; use Snowflake\Core\Str; @@ -18,75 +19,89 @@ use Snowflake\Snowflake; { - /** - * Inject constructor. - * @param string $className - * @param array $args - */ - public function __construct(private string $className, private array $args = []) - { - } + /** + * Inject constructor. + * @param string $className + * @param array $args + */ + public function __construct(private string $className, public bool $withContext = false, private array $args = []) + { + } - /** - * @param mixed $class - * @param mixed|null $method - * @return bool - * @throws ReflectionException - * @throws Exception - */ - public function execute(mixed $class, mixed $method = null): bool - { - $injectValue = $this->parseInjectValue(); - if (!($method = $this->getProperty($class, $method))) { - return false; - } - /** @var ReflectionProperty $class */ - if ($method->isPrivate() || $method->isProtected()) { - $method = 'set' . ucfirst(Str::convertUnderline($method->getName())); - if (!method_exists($class, $method)) { - return false; - } - $class->$method($injectValue); - } else { - $class->{$method->getName()} = $injectValue; - } - return true; - } + /** + * @param mixed $class + * @param mixed|null $method + * @return bool + * @throws ReflectionException + * @throws Exception + */ + public function execute(mixed $class, mixed $method = null): bool + { + if (!($method = $this->getProperty($class, $method))) { + return false; + } + /** @var ReflectionProperty $class */ + $injectValue = $this->parseInjectValue(); + if ($method->isPrivate() || $method->isProtected()) { + $this->setter($class, $method, $injectValue); + } else { + $class->{$method->getName()} = $injectValue; + } + return true; + } - /** - * @param $class - * @param $method - * @return ReflectionProperty|bool - */ - private function getProperty($class, $method): ReflectionProperty|bool - { - if ($method instanceof ReflectionProperty) { - return $method; - } - if (is_object($class)) $class = $class::class; - $method = Snowflake::getDi()->getClassProperty($class, $method); - if (!$method) { - return false; - } - return $method; - } + /** + * @param $class + * @param $method + * @param $injectValue + */ + private function setter($class, $method, $injectValue) + { + $method = 'set' . ucfirst(Str::convertUnderline($method->getName())); + if (!method_exists($class, $method)) { + return; + } + $class->$method($injectValue); + } - /** - * @return mixed - * @throws Exception - */ - private function parseInjectValue(): mixed - { - if (class_exists($this->className)) { - return Snowflake::getDi()->get($this->className, $this->args); - } else if (Snowflake::app()->has($this->className)) { - return Snowflake::app()->get($this->className); - } else { - return $this->className; - } - } + /** + * @param $class + * @param $method + * @return ReflectionProperty|bool + */ + private function getProperty($class, $method): ReflectionProperty|bool + { + if ($method instanceof ReflectionProperty && !$method->isStatic()) { + return $method; + } + if (is_object($class)) $class = $class::class; + $method = Snowflake::getDi()->getClassProperty($class, $method); + if (!$method || $method->isStatic()) { + return false; + } + return $method; + } + + + /** + * @return mixed + * @throws Exception + */ + private function parseInjectValue(): mixed + { + if ($this->withContext) { + return Context::getContext($this->className); + } + if (class_exists($this->className)) { + return Snowflake::getDi()->get($this->className, $this->args); + } else if (Snowflake::app()->has($this->className)) { + return Snowflake::app()->get($this->className); + } else { + return $this->className; + } + } } diff --git a/Annotation/Loader.php b/Annotation/Loader.php index 8c5085bb..2770c5c7 100644 --- a/Annotation/Loader.php +++ b/Annotation/Loader.php @@ -27,351 +27,337 @@ class Loader extends BaseObject { - private static array $_classes = []; + private static array $_classes = []; - private static array $_directory = []; + private static array $_directory = []; - private static array $_property = []; + private static array $_property = []; - private static array $_methods = []; + private static array $_methods = []; + + /** + * @return array + */ + public function getDirectory(): array + { + return static::$_directory; + } + + /** + * @param $path + * @param $namespace + * @throws Exception + */ + public function loader($path, $namespace) + { + $this->_scanDir(new DirectoryIterator($path), $namespace); + } - private array $_annotationMaps = []; + /** + * @return array + */ + public function getClasses(): array + { + return static::$_classes; + } - /** - * @return array - */ - public function getDirectory(): array - { - return static::$_directory; - } - - /** - * @param $path - * @param $namespace - * @throws Exception - */ - public function loader($path, $namespace) - { - $this->_scanDir(new DirectoryIterator($path), $namespace); - } + /** + * @param string $class + * @param string $property + * @return mixed + */ + public function getProperty(string $class, string $property = ''): mixed + { + if (!isset(static::$_property[$class])) { + return null; + } + if (!empty($property)) { + return static::$_property[$class][$property] ?? []; + } + return static::$_property[$class]; + } - /** - * @return array - */ - public function getClasses(): array - { - return static::$_classes; - } + /** + * @param string $class + * @param mixed $handler + * @return Loader + */ + public function injectProperty(string $class, object $handler): static + { + $properties = $this->getProperty($class); + if (empty($properties)) { + return $this; + } + foreach ($properties as $property => $attributes) { + foreach ($attributes as $attribute) { + $attribute->execute($handler, $property); + } + } + return $this; + } - /** - * @param string $class - * @param string $property - * @return mixed - */ - public function getProperty(string $class, string $property = ''): mixed - { - if (!isset(static::$_property[$class])) { - return null; - } - if (!empty($property)) { - return static::$_property[$class][$property] ?? []; - } - return static::$_property[$class]; - } + /** + * @param string $class + * @param string $method + * @return mixed + */ + public function getMethod(string $class, string $method = ''): array + { + if (!isset(static::$_methods[$class])) { + return []; + } + $properties = static::$_methods[$class]; + if (!empty($method) && isset($properties[$method])) { + return $properties[$method]; + } + return $properties; + } - /** - * @param string $class - * @param mixed $handler - * @return Loader - */ - public function injectProperty(string $class, object $handler): static - { - $properties = $this->getProperty($class); - if (empty($properties)) { - return $this; - } - foreach ($properties as $property => $attributes) { - foreach ($attributes as $attribute) { - $attribute->execute($handler, $property); - } - } - return $this; - } + /** + * @param string $class + * @return array + */ + public function getTarget(string $class): array + { + return static::$_classes[$class] ?? []; + } - /** - * @param string $class - * @param string $method - * @return mixed - */ - public function getMethod(string $class, string $method = ''): array - { - if (!isset(static::$_methods[$class])) { - return []; - } - $properties = static::$_methods[$class]; - if (!empty($method) && isset($properties[$method])) { - return $properties[$method]; - } - return $properties; - } + /** + * @param DirectoryIterator $paths + * @param $namespace + * @throws Exception + */ + public function _scanDir(DirectoryIterator $paths, $namespace) + { + foreach ($paths as $path) { + if ($path->isDot() || str_starts_with($path->getFilename(), '.')) { + continue; + } + if ($path->isDir()) { + $iterator = new DirectoryIterator($path->getRealPath()); + $directory = rtrim($path->getRealPath(), '/'); + if (!isset(static::$_directory[$directory])) { + static::$_directory[$directory] = []; + } + $this->_scanDir($iterator, $namespace); + } else { + $this->readFile($path, $namespace); + } + } + } - /** - * @param string $class - * @return array - */ - public function getTarget(string $class): array - { - return static::$_classes[$class] ?? []; - } + /** + * @param DirectoryIterator $path + * @param $namespace + * @throws Exception + */ + private function readFile(DirectoryIterator $path, $namespace) + { + try { + if ($path->getExtension() !== 'php') { + return; + } + $replace = $this->getReflect($path, $namespace); + if (empty($replace) || count($replace->getAttributes(Target::class)) < 1) { + return; + } + $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; + } catch (Throwable $throwable) { + $this->addError($throwable, 'throwable'); + } + } - /** - * @param DirectoryIterator $paths - * @param $namespace - * @throws Exception - */ - public function _scanDir(DirectoryIterator $paths, $namespace) - { - foreach ($paths as $path) { - if ($path->isDot() || str_starts_with($path->getFilename(), '.')) { - continue; - } - if ($path->isDir()) { - $iterator = new DirectoryIterator($path->getRealPath()); - $directory = rtrim($path->getRealPath(), '/'); - if (!isset(static::$_directory[$directory])) { - static::$_directory[$directory] = []; - } - $this->_scanDir($iterator, $namespace); - } else { - $this->readFile($path, $namespace); - } - } - } + /** + * @param DirectoryIterator $path + * @param string $namespace + * @return ReflectionClass|null + * @throws ReflectionException + * @throws NotFindClassException + */ + private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass + { + return Snowflake::getDi()->getReflect($this->explodeFileName($path, $namespace)); + } - /** - * @param DirectoryIterator $path - * @param $namespace - * @throws Exception - */ - private function readFile(DirectoryIterator $path, $namespace) - { - try { - if ($path->getExtension() !== 'php') { - return; - } - $replace = $this->getReflect($path, $namespace); - if (empty($replace) || count($replace->getAttributes(Target::class)) < 1) { - return; - } - $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; - } catch (Throwable $throwable) { - $this->addError($throwable, 'throwable'); - } - } + /** + * @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 DirectoryIterator $path - * @param string $namespace - * @return ReflectionClass|null - * @throws ReflectionException - * @throws NotFindClassException - */ - private function getReflect(DirectoryIterator $path, string $namespace): ?ReflectionClass - { - return Snowflake::getDi()->getReflect($this->explodeFileName($path, $namespace)); - } + /** + * @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 _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 _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 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 string $path + * @param string|array $outPath + * @throws Exception + */ + public function loadByDirectory(string $path, string|array $outPath = '') + { + try { + $path = '/' . trim($path, '/'); + foreach (static::$_directory as $key => $_path) { + $key = '/' . trim($key, '/'); + if (!str_starts_with($key, $path) || in_array($key, $outPath)) { + continue; + } + $this->execute($_path); + } + } catch (Throwable $exception) { + $this->addError($exception, 'throwable'); + } + } - /** - * @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 DirectoryIterator $path + * @param string $namespace + * @return string + */ + private function explodeFileName(DirectoryIterator $path, string $namespace): string + { + $replace = str_replace(APP_PATH . 'app', '', $path->getRealPath()); + + $replace = str_replace('.php', '', $replace); + $replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace); + $explode = explode('\\', $replace); + array_shift($explode); + + return $namespace . '\\' . implode('\\', $explode); + } - /** - * @param string $path - * @param string|array $outPath - * @throws Exception - */ - public function loadByDirectory(string $path, string|array $outPath = '') - { - try { - $path = '/' . trim($path, '/'); - foreach (static::$_directory as $key => $_path) { - $key = '/' . trim($key, '/'); - if (!str_starts_with($key, $path) || in_array($key, $outPath)) { - continue; - } - $this->execute($_path); - } - } catch (Throwable $exception) { - $this->addError($exception, 'throwable'); - } - } + /** + * @param string $filePath + * @param string $className + */ + public function appendFileToDirectory(string $filePath, string $className) + { + $array = explode('/', $filePath); + unset($array[count($array) - 1]); + + $array = '/' . trim(implode('/', $array), '/'); + + static::$_directory[$array][] = $className; + } - /** - * @param DirectoryIterator $path - * @param string $namespace - * @return string - */ - private function explodeFileName(DirectoryIterator $path, string $namespace): string - { - $replace = str_replace(APP_PATH . 'app', '', $path->getRealPath()); - - $replace = str_replace('.php', '', $replace); - $replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace); - $explode = explode('\\', $replace); - array_shift($explode); - - return $namespace . '\\' . implode('\\', $explode); - } + /** + * @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 string $filePath - * @param string $className - */ - public function appendFileToDirectory(string $filePath, string $className) - { - $array = explode('/', $filePath); - unset($array[count($array) - 1]); - - $array = '/' . trim(implode('/', $array), '/'); - - static::$_directory[$array][] = $className; - } - - - /** - * @param array $classes - * @throws Exception - */ - private function execute(array $classes) - { - if (empty($classes)) { - return; - } - $annotation = Snowflake::getAnnotation(); - - foreach ($classes as $className) { - if (!isset(static::$_methods[$className])) { - continue; - } - foreach (static::$_methods[$className] as $name => $attribute) { - $this->methods($attribute, $annotation, $className, $name); - } - } - } - - - /** - * @param $attribute - * @param $annotation - * @param $className - * @param $name - */ - private function methods($attribute, $annotation, $className, $name) - { - $handler = static::$_classes[$className]['handler']; - foreach ($attribute as $value) { - if ($value instanceof Relation) { - $annotation->addRelate($className, $value->name, $name); - } else if ($value instanceof Get) { - $annotation->addGets($className, $value->name, $name); - } else if ($value instanceof Set) { - $annotation->addSets($className, $value->name, $name); - } else { - $value->execute($handler, $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/HttpServer/Controller.php b/HttpServer/Controller.php index 68ff507d..8e1271bb 100644 --- a/HttpServer/Controller.php +++ b/HttpServer/Controller.php @@ -4,11 +4,14 @@ declare(strict_types=1); namespace HttpServer; +use Annotation\Inject; use Exception; use HttpServer\Abstracts\HttpService; use HttpServer\Http\HttpHeaders; use HttpServer\Http\HttpParams; use HttpServer\Http\Request; +use HttpServer\Http\Response; +use Snowflake\Abstracts\Input; use Snowflake\Abstracts\TraitApplication; use Snowflake\Snowflake; @@ -17,82 +20,29 @@ use Snowflake\Snowflake; * @package Snowflake\Snowflake\Web * @property-read HttpParams $input * @property-read HttpHeaders $headers - * @property-read Request $request */ -class Controller extends HttpService +class Controller { - use TraitApplication; + use TraitApplication; - /** - * Controller constructor. - * @param array $config - * @throws Exception - */ - public function __construct($config = []) - { - parent::__construct($config); - } + /** + * inject request + * + * @var \HttpServer\Http\Request + */ + #[Inject(className: 'request', withContext: true)] + protected Request $request; - /** - * @throws Exception - */ - public function init() - { - $annotation = Snowflake::getAnnotation(); - $annotation->injectProperty($this); - } - - - /** - * @return ?HttpParams - * @throws Exception - */ - public function getInput(): ?HttpParams - { - return \request()->params; - } - - /** - * @return ?HttpHeaders - * @throws Exception - */ - public function getHeaders(): ?HttpHeaders - { - return \request()->headers; - } - - /** - * @return Request|null - * @throws Exception - */ - public function getRequest(): ?Request - { - return \request(); - } - - - /** - * @param $name - * @return mixed - * @throws Exception - */ - public function __get($name): mixed - { - // TODO: Change the autogenerated stub - if (property_exists($this, $name)) { - return $this->$name; - } - - $method = 'get' . ucfirst($name); - if (method_exists($this, $method)) { - return $this->{$method}(); - } - - return Snowflake::app()->get($name); - } + /** + * inject response + * + * @var \HttpServer\Http\Response + */ + #[Inject('response')] + protected Response $response; } diff --git a/HttpServer/Http/Request.php b/HttpServer/Http/Request.php index da8152b6..f985c84c 100644 --- a/HttpServer/Http/Request.php +++ b/HttpServer/Http/Request.php @@ -38,462 +38,464 @@ defined('REQUEST_FAIL') or define('REQUEST_FAIL', 500); class Request extends HttpService { - public int $fd = 0; - - public ?HttpParams $params; - - public ?HttpHeaders $headers; - - public bool $isCli = FALSE; - - public float $startTime; - public ?array $clientInfo; - - public string $uri = ''; - - public int $statusCode = 200; - - /** @var string[] */ - private array $explode = []; - - const PLATFORM_MAC_OX = 'mac'; - const PLATFORM_IPHONE = 'iphone'; - const PLATFORM_ANDROID = 'android'; - const PLATFORM_WINDOWS = 'windows'; - - - const HTTP_POST = 'post'; - const HTTP_GET = 'get'; - const HTTP_CMD = 'rpc'; - const HTTP_LISTEN = 'listen'; - const HTTP_SOCKET = 'sw::socket'; - - - /** - * @var AuthIdentity|null - */ - private ?AuthIdentity $_grant = null; - - - /** - * @param $fd - */ - public function setFd($fd) - { - $this->fd = $fd; - } - - /** - * @return array|null - * @throws Exception - */ - public function getConnectInfo(): array|null - { - if (empty($this->fd)) { - return null; - } - $server = Snowflake::app()->getSwoole(); - - return $server->getClientInfo($this->fd); - } - - - /** - * @return int - */ - public function getClientId(): int - { - return $this->fd; - } - - - /** - * @return bool - */ - public function isFavicon(): bool - { - return $this->getUri() === 'favicon.ico'; - } - - /** - * @return AuthIdentity|null - */ - public function getIdentity(): ?AuthIdentity - { - return $this->_grant; - } - - /** - * @return bool - */ - public function isHead(): bool - { - $result = $this->headers->getHeader('request_method') == 'head'; - if ($result) { - $this->setStatus(101); - } else { - $this->setStatus(200); - } - return $result; - } - - /** - * @param $status - * @return mixed - */ - public function setStatus($status): mixed - { - return $this->statusCode = $status; - } - - /** - * @return int - */ - public function getStatus(): int - { - return $this->statusCode; - } - - /** - * @return bool - */ - public function getIsPackage(): bool - { - return $this->headers->getHeader('request_method') == 'package'; - } - - /** - * @return bool - */ - public function getIsReceive(): bool - { - return $this->headers->getHeader('request_method') == 'receive'; - } - - - /** - * @param $value - */ - public function setGrantAuthorization($value) - { - $this->_grant = $value; - } - - - /** - * @return bool - */ - public function hasGrant(): bool - { - return $this->_grant !== null; - } - - - /** - * @return string - */ - public function parseUri(): string - { - $array = []; - $explode = explode('/', $this->headers->getHeader('request_uri')); - foreach ($explode as $item) { - if (empty($item)) { - continue; - } - $array[] = $item; - } - return $this->uri = implode('/', ($this->explode = $array)); - } - - /** - * @return string[] - */ - public function getExplode(): array - { - return $this->explode; - } - - /** - * @return string - */ - #[Pure] public function getCurrent(): string - { - return current($this->explode); - } - - /** - * @return string - */ - public function getUri(): string - { - if (!$this->headers) { - return 'command exec.'; - } - if (!empty($this->uri)) { - return $this->uri; - } - $uri = $this->headers->getHeader('request_uri'); - $uri = ltrim($uri, '/'); - if (empty($uri)) return '/'; - return $uri; - } - - - /** - * @return mixed - * @throws Exception - */ - public function adapter(): void - { - if (!$this->isHead()) { - router()->dispatch(); - } - } - - - /** - * @return string|null - */ - public function getPlatform(): ?string - { - $user = $this->headers->getHeader('user-agent'); - $match = preg_match('/\(.*\)?/', $user, $output); - if (!$match || count($output) < 1) { - return null; - } - $output = strtolower(array_shift($output)); - if (strpos('mac', $output)) { - return 'mac'; - } else if (strpos('iphone', $output)) { - return 'iphone'; - } else if (strpos('android', $output)) { - return 'android'; - } else if (strpos('windows', $output)) { - return 'windows'; - } - return null; - } - - /** - * @return bool - */ - public function isIos(): bool - { - return $this->getPlatform() == static::PLATFORM_IPHONE; - } - - /** - * @return bool - */ - public function isAndroid(): bool - { - return $this->getPlatform() == static::PLATFORM_ANDROID; - } - - /** - * @return bool - */ - public function isMacOs(): bool - { - return $this->getPlatform() == static::PLATFORM_MAC_OX; - } - - /** - * @return bool - */ - public function isWindows(): bool - { - return $this->getPlatform() == static::PLATFORM_WINDOWS; - } - - /** - * @return bool - */ - public function getIsPost(): bool - { - return $this->getMethod() == 'post'; - } - - /** - * @return bool - * @throws Exception - */ - public function getIsHttp(): bool - { - return true; - } - - /** - * @return bool - */ - public function getIsOption(): bool - { - return $this->getMethod() == 'options'; - } - - /** - * @return bool - */ - public function getIsGet(): bool - { - return $this->getMethod() == 'get'; - } - - /** - * @return bool - */ - public function getIsDelete(): bool - { - return $this->getMethod() == 'delete'; - } - - /** - * @return string - * - * 获取请求类型 - */ - public function getMethod(): string - { - $method = $this->headers->get('request_method'); - if (empty($method)) { - return 'get'; - } - return strtolower($method); - } - - /** - * @return bool - */ - public function getIsCli(): bool - { - return $this->isCli === TRUE; - } - - - /** - * @param $name - * @param $value - * - * @throws Exception - */ - public function __set($name, $value) - { - $method = 'set' . ucfirst($name); - if (method_exists($this, $method)) { - $this->$method($value); - } else { - parent::__set($name, $value); // TODO: Change the autogenerated stub - } - } - - /** - * @return mixed|null - */ - #[Pure] public function getIp(): string|null - { - $headers = $this->headers->getHeaders(); - if (!empty($headers['remoteip'])) return $headers['remoteip']; - if (!empty($headers['x-forwarded-for'])) return $headers['x-forwarded-for']; - if (!empty($headers['request-ip'])) return $headers['request-ip']; - if (!empty($headers['remote_addr'])) return $headers['remote_addr']; - return NULL; - } - - /** - * @return string - */ - #[Pure] public function getRuntime(): string - { - return sprintf('%.5f', microtime(TRUE) - $this->startTime); - } - - /** - * @return string - */ - public function getDebug(): string - { - $mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳 - - $timestamp = floatval($mainstay); // 时间戳 - $milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒 - - $datetime = date("Y-m-d H:i:s", (int)$timestamp) . '.' . $milliseconds; - - $tmp = [ - '[Debug ' . $datetime . '] ', - $this->getIp(), - $this->getUri(), - '`' . $this->headers->getHeader('user-agent') . '`', - $this->getRuntime() - ]; - return implode(' ', $tmp); - } - - - /** - * @param $router - * @return bool - */ - public function is($router): bool - { - return $this->getUri() == $router; - } - - /** - * @return bool - */ - public function isNotFound(): bool - { - return Json::to(404, 'Page ' . $this->getUri() . ' not found.'); - } - - - /** - * @param \Swoole\Http\Request $request - * @return mixed - */ - public static function create(\Swoole\Http\Request $request, \Swoole\Http\Response $response): Request - { - /** @var Request $sRequest */ - $sRequest = Context::setContext('request', new Request()); - $sRequest->fd = $request->fd; - $sRequest->startTime = microtime(true); - - $sRequest->params = new HttpParams(Help::toArray($request->rawContent()), $request->get, $request->files); - if (!empty($request->post)) { - $sRequest->params->setPosts($request->post ?? []); - } - - $sRequest->headers = new HttpHeaders(array_merge($request->server, $request->header)); - $sRequest->uri = $sRequest->headers->get('request_uri'); - - $sRequest->parseUri(); - - HResponse::create($response); - return $sRequest; - } - - - /** - * @param $frame - * @param string $route - * @param string $event - * @return Request - */ - public static function socketQuery($frame, string $event = Socket::MESSAGE, string $route = 'event'): Request - { - $sRequest = new Request(); - $sRequest->fd = $frame->fd; - $sRequest->startTime = microtime(true); - - $sRequest->params = new HttpParams([], [], []); - $sRequest->headers = new HttpHeaders([]); - $sRequest->headers->replace('request_method', 'sw::socket'); - $sRequest->headers->replace('request_uri', $event . '::' . $route); - $sRequest->parseUri(); - - return Context::setContext('request', $sRequest); - } + public int $fd = 0; + + public ?HttpParams $params; + + public ?HttpHeaders $headers; + + public bool $isCli = FALSE; + + public float $startTime; + public ?array $clientInfo; + + public string $uri = ''; + + public int $statusCode = 200; + + /** @var string[] */ + private array $explode = []; + + const PLATFORM_MAC_OX = 'mac'; + const PLATFORM_IPHONE = 'iphone'; + const PLATFORM_ANDROID = 'android'; + const PLATFORM_WINDOWS = 'windows'; + + + const HTTP_POST = 'post'; + const HTTP_GET = 'get'; + const HTTP_CMD = 'rpc'; + const HTTP_LISTEN = 'listen'; + const HTTP_SOCKET = 'sw::socket'; + + + /** + * @var AuthIdentity|null + */ + private ?AuthIdentity $_grant = null; + + + /** + * @param $fd + */ + public function setFd($fd) + { + $this->fd = $fd; + } + + /** + * @return array|null + * @throws Exception + */ + public function getConnectInfo(): array|null + { + if (empty($this->fd)) { + return null; + } + $server = Snowflake::app()->getSwoole(); + + return $server->getClientInfo($this->fd); + } + + + /** + * @return int + */ + public function getClientId(): int + { + return $this->fd; + } + + + /** + * @return bool + */ + public function isFavicon(): bool + { + return $this->getUri() === 'favicon.ico'; + } + + /** + * @return AuthIdentity|null + */ + public function getIdentity(): ?AuthIdentity + { + return $this->_grant; + } + + /** + * @return bool + */ + public function isHead(): bool + { + $result = $this->headers->getHeader('request_method') == 'head'; + if ($result) { + $this->setStatus(101); + } else { + $this->setStatus(200); + } + return $result; + } + + /** + * @param $status + * @return mixed + */ + public function setStatus($status): mixed + { + return $this->statusCode = $status; + } + + /** + * @return int + */ + public function getStatus(): int + { + return $this->statusCode; + } + + /** + * @return bool + */ + public function getIsPackage(): bool + { + return $this->headers->getHeader('request_method') == 'package'; + } + + /** + * @return bool + */ + public function getIsReceive(): bool + { + return $this->headers->getHeader('request_method') == 'receive'; + } + + + /** + * @param $value + */ + public function setGrantAuthorization($value) + { + $this->_grant = $value; + } + + + /** + * @return bool + */ + public function hasGrant(): bool + { + return $this->_grant !== null; + } + + + /** + * @return string + */ + public function parseUri(): string + { + $array = []; + $explode = explode('/', $this->headers->getHeader('request_uri')); + foreach ($explode as $item) { + if (empty($item)) { + continue; + } + $array[] = $item; + } + return $this->uri = implode('/', ($this->explode = $array)); + } + + /** + * @return string[] + */ + public function getExplode(): array + { + return $this->explode; + } + + /** + * @return string + */ + #[Pure] public function getCurrent(): string + { + return current($this->explode); + } + + /** + * @return string + */ + public function getUri(): string + { + if (!$this->headers) { + return 'command exec.'; + } + if (!empty($this->uri)) { + return $this->uri; + } + $uri = $this->headers->getHeader('request_uri'); + $uri = ltrim($uri, '/'); + if (empty($uri)) return '/'; + return $uri; + } + + + /** + * @return mixed + * @throws Exception + */ + public function adapter(): void + { + if (!$this->isHead()) { + router()->dispatch(); + } + } + + + /** + * @return string|null + */ + public function getPlatform(): ?string + { + $user = $this->headers->getHeader('user-agent'); + $match = preg_match('/\(.*\)?/', $user, $output); + if (!$match || count($output) < 1) { + return null; + } + $output = strtolower(array_shift($output)); + if (strpos('mac', $output)) { + return 'mac'; + } else if (strpos('iphone', $output)) { + return 'iphone'; + } else if (strpos('android', $output)) { + return 'android'; + } else if (strpos('windows', $output)) { + return 'windows'; + } + return null; + } + + /** + * @return bool + */ + public function isIos(): bool + { + return $this->getPlatform() == static::PLATFORM_IPHONE; + } + + /** + * @return bool + */ + public function isAndroid(): bool + { + return $this->getPlatform() == static::PLATFORM_ANDROID; + } + + /** + * @return bool + */ + public function isMacOs(): bool + { + return $this->getPlatform() == static::PLATFORM_MAC_OX; + } + + /** + * @return bool + */ + public function isWindows(): bool + { + return $this->getPlatform() == static::PLATFORM_WINDOWS; + } + + /** + * @return bool + */ + public function getIsPost(): bool + { + return $this->getMethod() == 'post'; + } + + /** + * @return bool + * @throws Exception + */ + public function getIsHttp(): bool + { + return true; + } + + /** + * @return bool + */ + public function getIsOption(): bool + { + return $this->getMethod() == 'options'; + } + + /** + * @return bool + */ + public function getIsGet(): bool + { + return $this->getMethod() == 'get'; + } + + /** + * @return bool + */ + public function getIsDelete(): bool + { + return $this->getMethod() == 'delete'; + } + + /** + * @return string + * + * 获取请求类型 + */ + public function getMethod(): string + { + $method = $this->headers->get('request_method'); + if (empty($method)) { + return 'get'; + } + return strtolower($method); + } + + /** + * @return bool + */ + public function getIsCli(): bool + { + return $this->isCli === TRUE; + } + + + /** + * @param $name + * @param $value + * + * @throws Exception + */ + public function __set($name, $value) + { + $method = 'set' . ucfirst($name); + if (method_exists($this, $method)) { + $this->$method($value); + } else { + parent::__set($name, $value); // TODO: Change the autogenerated stub + } + } + + /** + * @return mixed|null + */ + #[Pure] public function getIp(): string|null + { + $headers = $this->headers->getHeaders(); + if (!empty($headers['remoteip'])) return $headers['remoteip']; + if (!empty($headers['x-forwarded-for'])) return $headers['x-forwarded-for']; + if (!empty($headers['request-ip'])) return $headers['request-ip']; + if (!empty($headers['remote_addr'])) return $headers['remote_addr']; + return NULL; + } + + /** + * @return string + */ + #[Pure] public function getRuntime(): string + { + return sprintf('%.5f', microtime(TRUE) - $this->startTime); + } + + /** + * @return string + */ + public function getDebug(): string + { + $mainstay = sprintf("%.6f", microtime(true)); // 带毫秒的时间戳 + + $timestamp = floatval($mainstay); // 时间戳 + $milliseconds = round(($mainstay - $timestamp) * 1000); // 毫秒 + + $datetime = date("Y-m-d H:i:s", (int)$timestamp) . '.' . $milliseconds; + + $tmp = [ + '[Debug ' . $datetime . '] ', + $this->getIp(), + $this->getUri(), + '`' . $this->headers->getHeader('user-agent') . '`', + $this->getRuntime() + ]; + return implode(' ', $tmp); + } + + + /** + * @param $router + * @return bool + */ + public function is($router): bool + { + return $this->getUri() == $router; + } + + /** + * @return bool + */ + public function isNotFound(): bool + { + return Json::to(404, 'Page ' . $this->getUri() . ' not found.'); + } + + + /** + * @param \Swoole\Http\Request $request + * @return mixed + */ + public static function create(\Swoole\Http\Request $request): Request + { + /** @var Request $sRequest */ + $sRequest = Context::setContext('request', new Request()); + $sRequest->fd = $request->fd; + $sRequest->startTime = microtime(true); + + $sRequest->params = new HttpParams(Help::toArray($request->rawContent()), $request->get, $request->files); + if (!empty($request->post)) { + $sRequest->params->setPosts($request->post ?? []); + } + + $sRequest->headers = new HttpHeaders(array_merge($request->server, $request->header)); + $sRequest->uri = $sRequest->headers->get('request_uri'); + + $sRequest->parseUri(); + + Context::setContext('input', $sRequest->params); + Context::setContext('header', $sRequest->headers); + + return $sRequest; + } + + + /** + * @param $frame + * @param string $route + * @param string $event + * @return Request + */ + public static function socketQuery($frame, string $event = Socket::MESSAGE, string $route = 'event'): Request + { + $sRequest = new Request(); + $sRequest->fd = $frame->fd; + $sRequest->startTime = microtime(true); + + $sRequest->params = new HttpParams([], [], []); + $sRequest->headers = new HttpHeaders([]); + $sRequest->headers->replace('request_method', 'sw::socket'); + $sRequest->headers->replace('request_uri', $event . '::' . $route); + $sRequest->parseUri(); + + return Context::setContext('request', $sRequest); + } } diff --git a/Server/HTTPServerListener.php b/Server/HTTPServerListener.php index ce9627c4..f8688f3a 100644 --- a/Server/HTTPServerListener.php +++ b/Server/HTTPServerListener.php @@ -32,8 +32,6 @@ class HTTPServerListener extends Abstracts\Server private Router $router; - private ApplicationStore $store; - /** * HTTPServerListener constructor. @@ -42,7 +40,6 @@ class HTTPServerListener extends Abstracts\Server public function __construct() { $this->router = Snowflake::getApp('router'); - $this->store = ApplicationStore::getStore(); parent::__construct(); } @@ -105,16 +102,19 @@ class HTTPServerListener extends Abstracts\Server */ public function onRequest(Request $request, Response $response) { + [$sRequest, $sResponse] = [HRequest::create($request), HResponse::create($response)]; try { - if (HRequest::create($request, $response)->is('favicon.ico')) { + if ($sRequest->is('favicon.ico')) { + $this->router->status404(); + } else if (!($node = $this->router->find_path($sRequest))) { $this->router->status404(); } else { - $this->router->dispatch(); + $sResponse->send($node->dispatch(), 200); } } catch (Error | Throwable $exception) { - $response->setHeader('Content-Type', 'text/html; charset=utf-8'); - $response->status($exception->getCode() == 0 ? 500 : $exception->getCode()); - $response->end($exception->getMessage()); + $sResponse->addHeader('Content-Type', 'text/html; charset=utf-8'); + $sResponse->send($exception->getMessage(), + $exception->getCode() == 0 ? 500 : $exception->getCode()); } finally { $this->_event->dispatch(Event::SYSTEM_RESOURCE_RELEASES); } diff --git a/System/Abstracts/BaseApplication.php b/System/Abstracts/BaseApplication.php index 653dc497..bc5e9309 100644 --- a/System/Abstracts/BaseApplication.php +++ b/System/Abstracts/BaseApplication.php @@ -13,6 +13,8 @@ namespace Snowflake\Abstracts; use Annotation\Annotation as SAnnotation; use Exception; use HttpServer\Client\Http2; +use HttpServer\Http\HttpHeaders; +use HttpServer\Http\HttpParams; use HttpServer\Http\Request; use HttpServer\Http\Response; use HttpServer\HttpFilter; @@ -48,427 +50,429 @@ use Swoole\Table; abstract class BaseApplication extends Service { - use TraitApplication; - - - /** - * @var string - */ - public string $storage = APP_PATH . 'storage'; - - public string $envPath = APP_PATH . '.env'; - - /** - * Init constructor. - * - * @param array $config - * - * @throws - */ - public function __construct(array $config = []) - { - Snowflake::init($this); - - $this->moreComponents(); - $this->parseInt($config); - $this->parseEvents($config); - $this->initErrorHandler(); - $this->enableEnvConfig(); - - parent::__construct($config); - } - - - /** - * @return array - */ - public function enableEnvConfig(): array - { - if (!file_exists($this->envPath)) { - return []; - } - $lines = $this->readLinesFromFile($this->envPath); - foreach ($lines as $line) { - if (!$this->isComment($line) && $this->looksLikeSetter($line)) { - [$key, $value] = explode('=', $line); - putenv(trim($key) . '=' . trim($value)); - } - } - return $lines; - } - - - /** - * Read lines from the file, auto detecting line endings. - * - * @param string $filePath - * - * @return array - */ - protected function readLinesFromFile(string $filePath): array - { - // Read file into an array of lines with auto-detected line endings - $autodetect = ini_get('auto_detect_line_endings'); - ini_set('auto_detect_line_endings', '1'); - $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - ini_set('auto_detect_line_endings', $autodetect); - - return $lines; - } - - /** - * Determine if the line in the file is a comment, e.g. begins with a #. - * - * @param string $line - * - * @return bool - */ - protected function isComment(string $line): bool - { - $line = ltrim($line); - - return isset($line[0]) && $line[0] === '#'; - } - - /** - * Determine if the given line looks like it's setting a variable. - * - * @param string $line - * - * @return bool - */ - #[Pure] protected function looksLikeSetter(string $line): bool - { - return str_contains($line, '='); - } - - - /** - * @param $config - * - * @throws - */ - public function parseInt($config) - { - Config::sets($config); - if ($storage = Config::get('storage', 'storage')) { - if (!str_contains($storage, APP_PATH)) { - $storage = APP_PATH . $storage . '/'; - } - if (!is_dir($storage)) { - mkdir($storage); - } - if (!is_dir($storage) || !is_writeable($storage)) { - throw new InitException("Directory {$storage} does not have write permission"); - } - } - } - - - /** - * @param $config - * - * @throws - */ - public function parseEvents($config) - { - if (!isset($config['events']) || !is_array($config['events'])) { - return; - } - foreach ($config['events'] as $key => $value) { - if (is_string($value)) { - $value = Snowflake::createObject($value); - } - $this->addEvent($key, $value); - } - } - - - /** - * @param $key - * @param $value - * @throws InitException - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - private function addEvent($key, $value): void - { - if ($value instanceof \Closure) { - Event::on($key, $value, [], true); - return; - } - if (is_object($value)) { - Event::on($key, $value, [], true); - return; - } - if (is_array($value)) { - if (is_object($value[0]) && !($value[0] instanceof \Closure)) { - Event::on($key, $value, [], true); - return; - } - - if (is_string($value[0])) { - $value[0] = Snowflake::createObject($value[0]); - Event::on($key, $value, [], true); - return; - } - - foreach ($value as $item) { - if (!is_callable($item, true)) { - throw new InitException("Class does not hav callback."); - } - Event::on($key, $item, [], true); - } - } - - } - - - /** - * @param $name - * @return mixed - * @throws Exception - */ - public function clone($name): mixed - { - return clone $this->get($name); - } - - /** - * - * @throws Exception - */ - public function initErrorHandler() - { - $this->get('error')->register(); - } - - /** - * @return mixed - */ - public function getLocalIps(): mixed - { - return swoole_get_local_ip(); - } - - /** - * @return mixed - */ - public function getFirstLocal(): mixed - { - return current($this->getLocalIps()); - } - - - /** - * @return Logger - * @throws Exception - */ - public function getLogger(): Logger - { - return $this->get('logger'); - } - - - /** - * @return Producer - * @throws Exception - */ - public function getKafka(): Producer - { - return $this->get('kafka'); - } - - - /** - * @return \Redis|Redis - * @throws Exception - */ - public function getRedis(): Redis|\Redis - { - return $this->get('redis'); - } - - /** - * @param $ip - * @return bool - */ - public function isLocal($ip): bool - { - return $this->getFirstLocal() == $ip; - } - - - /** - * @return ErrorHandler - * @throws Exception - */ - public function getError(): ErrorHandler - { - return $this->get('error'); - } - - - /** - * @return Connection - * @throws Exception - */ - public function getMysqlFromPool(): Connection - { - return $this->get('connections'); - } - - - /** - * @return SRedis - * @throws Exception - */ - public function getRedisFromPool(): SRedis - { - return $this->get('redis_connections'); - } - - - /** - * @param $name - * @return Table - * @throws Exception - */ - public function getTable($name): Table - { - return $this->get($name); - } - - - /** - * @return Config - * @throws Exception - */ - public function getConfig(): Config - { - return $this->get('config'); - } - - - /** - * @return Router - * @throws Exception - */ - public function getRouter(): Router - { - return $this->get('router'); - } - - - /** - * @return Jwt - * @throws Exception - */ - public function getJwt(): Jwt - { - return $this->get('jwt'); - } - - - /** - * @return Server - * @throws Exception - */ - public function getServer(): Server - { - return $this->get('server'); - } - - - /** - * @return \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null - */ - public function getSwoole(): \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null - { - return ServerManager::getContext()->getServer(); - } - - - /** - * @return SAnnotation - * @throws Exception - */ - public function getAnnotation(): SAnnotation - { - return $this->get('annotation'); - } - - - /** - * @return Async - * @throws Exception - */ - public function getAsync(): Async - { - return $this->get('async'); - } - - - /** - * @return \Rpc\Producer - * @throws Exception - */ - public function getRpc(): \Rpc\Producer - { - return $this->get('rpc'); - } - - - /** - * @return Channel - * @throws Exception - */ - public function getChannel(): Channel - { - return $this->get('channel'); - } - - - /** - * @return Pool - * @throws Exception - */ - public function getClientsPool(): Pool - { - return $this->get('clientsPool'); - } - - - /** - * @throws Exception - */ - protected function moreComponents(): void - { - $this->setComponents([ - 'error' => ['class' => ErrorHandler::class], - 'connections' => ['class' => Connection::class], - 'redis_connections' => ['class' => SRedis::class], - 'clientsPool' => ['class' => Pool::class], - 'config' => ['class' => Config::class], - 'logger' => ['class' => Logger::class], - 'annotation' => ['class' => SAnnotation::class], - 'router' => ['class' => Router::class], - 'event' => ['class' => Event::class], - 'redis' => ['class' => Redis::class], - 'aop' => ['class' => Aop::class], - 'jwt' => ['class' => Jwt::class], - 'async' => ['class' => Async::class], - 'kafka-container' => ['class' => TaskContainer::class], - 'filter' => ['class' => HttpFilter::class], - 'goto' => ['class' => BaseGoto::class], - 'response' => ['class' => Response::class], - 'request' => ['class' => Request::class], - 'channel' => ['class' => Channel::class], - 'rpc' => ['class' => \Rpc\Producer::class], - 'rpc-service' => ['class' => \Rpc\Service::class], - 'http2' => ['class' => Http2::class], - 'shutdown' => ['class' => Shutdown::class], - ]); - } + use TraitApplication; + + + /** + * @var string + */ + public string $storage = APP_PATH . 'storage'; + + public string $envPath = APP_PATH . '.env'; + + /** + * Init constructor. + * + * @param array $config + * + * @throws + */ + public function __construct(array $config = []) + { + Snowflake::init($this); + + $this->moreComponents(); + $this->parseInt($config); + $this->parseEvents($config); + $this->initErrorHandler(); + $this->enableEnvConfig(); + + parent::__construct($config); + } + + + /** + * @return array + */ + public function enableEnvConfig(): array + { + if (!file_exists($this->envPath)) { + return []; + } + $lines = $this->readLinesFromFile($this->envPath); + foreach ($lines as $line) { + if (!$this->isComment($line) && $this->looksLikeSetter($line)) { + [$key, $value] = explode('=', $line); + putenv(trim($key) . '=' . trim($value)); + } + } + return $lines; + } + + + /** + * Read lines from the file, auto detecting line endings. + * + * @param string $filePath + * + * @return array + */ + protected function readLinesFromFile(string $filePath): array + { + // Read file into an array of lines with auto-detected line endings + $autodetect = ini_get('auto_detect_line_endings'); + ini_set('auto_detect_line_endings', '1'); + $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + ini_set('auto_detect_line_endings', $autodetect); + + return $lines; + } + + /** + * Determine if the line in the file is a comment, e.g. begins with a #. + * + * @param string $line + * + * @return bool + */ + protected function isComment(string $line): bool + { + $line = ltrim($line); + + return isset($line[0]) && $line[0] === '#'; + } + + /** + * Determine if the given line looks like it's setting a variable. + * + * @param string $line + * + * @return bool + */ + #[Pure] protected function looksLikeSetter(string $line): bool + { + return str_contains($line, '='); + } + + + /** + * @param $config + * + * @throws + */ + public function parseInt($config) + { + Config::sets($config); + if ($storage = Config::get('storage', 'storage')) { + if (!str_contains($storage, APP_PATH)) { + $storage = APP_PATH . $storage . '/'; + } + if (!is_dir($storage)) { + mkdir($storage); + } + if (!is_dir($storage) || !is_writeable($storage)) { + throw new InitException("Directory {$storage} does not have write permission"); + } + } + } + + + /** + * @param $config + * + * @throws + */ + public function parseEvents($config) + { + if (!isset($config['events']) || !is_array($config['events'])) { + return; + } + foreach ($config['events'] as $key => $value) { + if (is_string($value)) { + $value = Snowflake::createObject($value); + } + $this->addEvent($key, $value); + } + } + + + /** + * @param $key + * @param $value + * @throws InitException + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + private function addEvent($key, $value): void + { + if ($value instanceof \Closure) { + Event::on($key, $value, [], true); + return; + } + if (is_object($value)) { + Event::on($key, $value, [], true); + return; + } + if (is_array($value)) { + if (is_object($value[0]) && !($value[0] instanceof \Closure)) { + Event::on($key, $value, [], true); + return; + } + + if (is_string($value[0])) { + $value[0] = Snowflake::createObject($value[0]); + Event::on($key, $value, [], true); + return; + } + + foreach ($value as $item) { + if (!is_callable($item, true)) { + throw new InitException("Class does not hav callback."); + } + Event::on($key, $item, [], true); + } + } + + } + + + /** + * @param $name + * @return mixed + * @throws Exception + */ + public function clone($name): mixed + { + return clone $this->get($name); + } + + /** + * + * @throws Exception + */ + public function initErrorHandler() + { + $this->get('error')->register(); + } + + /** + * @return mixed + */ + public function getLocalIps(): mixed + { + return swoole_get_local_ip(); + } + + /** + * @return mixed + */ + public function getFirstLocal(): mixed + { + return current($this->getLocalIps()); + } + + + /** + * @return Logger + * @throws Exception + */ + public function getLogger(): Logger + { + return $this->get('logger'); + } + + + /** + * @return Producer + * @throws Exception + */ + public function getKafka(): Producer + { + return $this->get('kafka'); + } + + + /** + * @return \Redis|Redis + * @throws Exception + */ + public function getRedis(): Redis|\Redis + { + return $this->get('redis'); + } + + /** + * @param $ip + * @return bool + */ + public function isLocal($ip): bool + { + return $this->getFirstLocal() == $ip; + } + + + /** + * @return ErrorHandler + * @throws Exception + */ + public function getError(): ErrorHandler + { + return $this->get('error'); + } + + + /** + * @return Connection + * @throws Exception + */ + public function getMysqlFromPool(): Connection + { + return $this->get('connections'); + } + + + /** + * @return SRedis + * @throws Exception + */ + public function getRedisFromPool(): SRedis + { + return $this->get('redis_connections'); + } + + + /** + * @param $name + * @return Table + * @throws Exception + */ + public function getTable($name): Table + { + return $this->get($name); + } + + + /** + * @return Config + * @throws Exception + */ + public function getConfig(): Config + { + return $this->get('config'); + } + + + /** + * @return Router + * @throws Exception + */ + public function getRouter(): Router + { + return $this->get('router'); + } + + + /** + * @return Jwt + * @throws Exception + */ + public function getJwt(): Jwt + { + return $this->get('jwt'); + } + + + /** + * @return Server + * @throws Exception + */ + public function getServer(): Server + { + return $this->get('server'); + } + + + /** + * @return \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null + */ + public function getSwoole(): \Swoole\Http\Server|\Swoole\Server|\Swoole\WebSocket\Server|null + { + return ServerManager::getContext()->getServer(); + } + + + /** + * @return SAnnotation + * @throws Exception + */ + public function getAnnotation(): SAnnotation + { + return $this->get('annotation'); + } + + + /** + * @return Async + * @throws Exception + */ + public function getAsync(): Async + { + return $this->get('async'); + } + + + /** + * @return \Rpc\Producer + * @throws Exception + */ + public function getRpc(): \Rpc\Producer + { + return $this->get('rpc'); + } + + + /** + * @return Channel + * @throws Exception + */ + public function getChannel(): Channel + { + return $this->get('channel'); + } + + + /** + * @return Pool + * @throws Exception + */ + public function getClientsPool(): Pool + { + return $this->get('clientsPool'); + } + + + /** + * @throws Exception + */ + protected function moreComponents(): void + { + $this->setComponents([ + 'error' => ['class' => ErrorHandler::class], + 'connections' => ['class' => Connection::class], + 'redis_connections' => ['class' => SRedis::class], + 'clientsPool' => ['class' => Pool::class], + 'config' => ['class' => Config::class], + 'logger' => ['class' => Logger::class], + 'annotation' => ['class' => SAnnotation::class], + 'router' => ['class' => Router::class], + 'event' => ['class' => Event::class], + 'redis' => ['class' => Redis::class], + 'aop' => ['class' => Aop::class], + 'input' => ['class' => HttpParams::class], + 'header' => ['class' => HttpHeaders::class], + 'jwt' => ['class' => Jwt::class], + 'async' => ['class' => Async::class], + 'kafka-container' => ['class' => TaskContainer::class], + 'filter' => ['class' => HttpFilter::class], + 'goto' => ['class' => BaseGoto::class], + 'response' => ['class' => Response::class], + 'request' => ['class' => Request::class], + 'channel' => ['class' => Channel::class], + 'rpc' => ['class' => \Rpc\Producer::class], + 'rpc-service' => ['class' => \Rpc\Service::class], + 'http2' => ['class' => Http2::class], + 'shutdown' => ['class' => Shutdown::class], + ]); + } }