modify
This commit is contained in:
+79
-64
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+294
-308
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+19
-69
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
+458
-456
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user