mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-17 20:54:52 +08:00
PHP80 小修 (#187)
* migrate-php80 fix styles fix static analyse * fix some bugs
This commit is contained in:
parent
da516b487d
commit
8ff7da4d23
@ -84,5 +84,5 @@ define('ZM_STATE_DIR', TMP_DIR . '/.zm_' . sha1(ZM_INIT_TIME . FRAMEWORK_ROOT_DI
|
||||
&& define('SWOOLE_HOOK_NATIVE_CURL', 4096)
|
||||
&& define('SWOOLE_HOOK_BLOCKING_FUNCTION', 8192)
|
||||
&& define('SWOOLE_HOOK_SOCKETS', 16384)
|
||||
&& define('SWOOLE_HOOK_ALL', 2147481599)
|
||||
&& define('SWOOLE_HOOK_ALL', 2_147_481_599)
|
||||
);
|
||||
|
||||
@ -28,7 +28,7 @@ if (function_exists('zm_internal_errcode')) {
|
||||
*/
|
||||
function zm_dir(string $dir): string
|
||||
{
|
||||
if (strpos($dir, 'phar://') === 0) {
|
||||
if (str_starts_with($dir, 'phar://')) {
|
||||
return $dir;
|
||||
}
|
||||
return str_replace('/', DIRECTORY_SEPARATOR, $dir);
|
||||
@ -46,10 +46,8 @@ function zm_exec(string $cmd): ExecutionResult
|
||||
|
||||
/**
|
||||
* sleep 指定时间,单位为秒(最小单位为1毫秒,即0.001)
|
||||
*
|
||||
* @param float|int $time
|
||||
*/
|
||||
function zm_sleep($time)
|
||||
function zm_sleep(float|int $time)
|
||||
{
|
||||
Adaptive::sleep($time);
|
||||
}
|
||||
@ -64,10 +62,8 @@ function coroutine(): ?CoroutineInterface
|
||||
|
||||
/**
|
||||
* 获取内部错误码
|
||||
*
|
||||
* @param int|string $code
|
||||
*/
|
||||
function zm_internal_errcode($code): string
|
||||
function zm_internal_errcode(int|string $code): string
|
||||
{
|
||||
return "[ErrCode:{$code}] ";
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation;
|
||||
|
||||
abstract class AnnotationBase implements \IteratorAggregate
|
||||
abstract class AnnotationBase implements \IteratorAggregate, \Stringable
|
||||
{
|
||||
/** @var array|\Closure|string 方法名或闭包 */
|
||||
public \Closure|string|array $method = '';
|
||||
@ -13,9 +13,9 @@ abstract class AnnotationBase implements \IteratorAggregate
|
||||
|
||||
public array $group = [];
|
||||
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
$str = __CLASS__ . ': ';
|
||||
$str = self::class . ': ';
|
||||
foreach ($this as $k => $v) {
|
||||
$str .= "\n\t" . $k . ' => ';
|
||||
if (is_string($v)) {
|
||||
@ -39,10 +39,8 @@ abstract class AnnotationBase implements \IteratorAggregate
|
||||
|
||||
/**
|
||||
* 在 InstantPlugin 下调用,设置回调或匿名函数
|
||||
*
|
||||
* @param \Closure|string $method
|
||||
*/
|
||||
public function on($method): AnnotationBase
|
||||
public function on(\Closure|callable|string $method): AnnotationBase
|
||||
{
|
||||
$this->method = $method;
|
||||
return $this;
|
||||
|
||||
@ -58,8 +58,7 @@ class AnnotationHandler
|
||||
/**
|
||||
* 设置执行前判断注解是否应该被执行的检查回调函数
|
||||
*
|
||||
* @param callable $rule 回调函数
|
||||
* @return $this
|
||||
* @param callable $rule 回调函数
|
||||
*/
|
||||
public function setRuleCallback(callable $rule): AnnotationHandler
|
||||
{
|
||||
@ -71,8 +70,7 @@ class AnnotationHandler
|
||||
/**
|
||||
* 设置成功执行后有返回值时执行的返回值后续逻辑回调函数
|
||||
*
|
||||
* @param callable $return 回调函数
|
||||
* @return $this
|
||||
* @param callable $return 回调函数
|
||||
*/
|
||||
public function setReturnCallback(callable $return): AnnotationHandler
|
||||
{
|
||||
@ -88,7 +86,7 @@ class AnnotationHandler
|
||||
* @param mixed ...$params 传入的参数们
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function handleAll(...$params)
|
||||
public function handleAll(mixed ...$params)
|
||||
{
|
||||
try {
|
||||
// 遍历注册的注解
|
||||
|
||||
@ -138,7 +138,7 @@ class AnnotationParser
|
||||
|
||||
// 预处理0:排除所有非继承于 AnnotationBase 的注解
|
||||
if (!$vs instanceof AnnotationBase) {
|
||||
logger()->notice(get_class($vs) . ' is not extended from ' . AnnotationBase::class);
|
||||
logger()->notice($vs::class . ' is not extended from ' . AnnotationBase::class);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ class AnnotationParser
|
||||
foreach ($methods_annotations as $method_anno) {
|
||||
// 预处理3.0:排除所有非继承于 AnnotationBase 的注解
|
||||
if (!$method_anno instanceof AnnotationBase) {
|
||||
logger()->notice('Binding annotation ' . get_class($method_anno) . ' to ' . $v . '::' . $method_name . ' is not extended from ' . AnnotationBase::class);
|
||||
logger()->notice('Binding annotation ' . $method_anno::class . ' to ' . $v . '::' . $method_name . ' is not extended from ' . AnnotationBase::class);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -225,11 +225,11 @@ class AnnotationParser
|
||||
if ($class_annotation instanceof ErgodicAnnotation) {
|
||||
continue;
|
||||
}
|
||||
$o[get_class($class_annotation)][] = $class_annotation;
|
||||
$o[$class_annotation::class][] = $class_annotation;
|
||||
}
|
||||
foreach (($obj['methods_annotations'] ?? []) as $methods_annotations) {
|
||||
foreach ($methods_annotations as $annotation) {
|
||||
$o[get_class($annotation)][] = $annotation;
|
||||
$o[$annotation::class][] = $annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -238,7 +238,7 @@ class AnnotationParser
|
||||
|
||||
public function parseSpecial($annotation, $same_method_annotations = null): ?bool
|
||||
{
|
||||
foreach (($this->special_parsers[get_class($annotation)] ?? []) as $parser) {
|
||||
foreach (($this->special_parsers[$annotation::class] ?? []) as $parser) {
|
||||
$result = $parser($annotation, $same_method_annotations);
|
||||
if (is_bool($result)) {
|
||||
return $result;
|
||||
|
||||
@ -23,20 +23,16 @@ use ZM\Annotation\Interfaces\Level;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||
class BindEvent extends AnnotationBase implements Level
|
||||
{
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $event_class;
|
||||
|
||||
public int $level = 800;
|
||||
|
||||
/**
|
||||
* @param string $event_class 绑定事件的类型
|
||||
*/
|
||||
public function __construct(string $event_class, int $level = 800)
|
||||
{
|
||||
$this->event_class = $event_class;
|
||||
$this->level = $level;
|
||||
public function __construct(
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $event_class,
|
||||
public int $level = 800
|
||||
) {
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
|
||||
@ -19,10 +19,7 @@ use ZM\Annotation\AnnotationBase;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||
class Init extends AnnotationBase
|
||||
{
|
||||
public int $worker = 0;
|
||||
|
||||
public function __construct(int $worker = 0)
|
||||
public function __construct(public int $worker = 0)
|
||||
{
|
||||
$this->worker = $worker;
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,13 +20,11 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS)]
|
||||
class Controller extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $prefix = '';
|
||||
|
||||
public function __construct(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
public function __construct(
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $prefix
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,26 +19,18 @@ use ZM\Annotation\AnnotationBase;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||
class Route extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $route = '';
|
||||
|
||||
public string $name = '';
|
||||
|
||||
public array $request_method = ['GET', 'POST'];
|
||||
|
||||
/**
|
||||
* Routing path params binding. eg. {"id"="\d+"}
|
||||
*/
|
||||
public array $params = [];
|
||||
|
||||
public function __construct($route, $name = '', $request_method = ['GET', 'POST'], $params = [])
|
||||
{
|
||||
$this->route = $route;
|
||||
$this->name = $name;
|
||||
$this->request_method = $request_method;
|
||||
$this->params = $params;
|
||||
public function __construct(
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public $route,
|
||||
public $name = '',
|
||||
public $request_method = ['GET', 'POST'],
|
||||
/**
|
||||
* Routing path params binding. eg. {"id"="\d+"}
|
||||
*/
|
||||
public $params = []
|
||||
) {
|
||||
}
|
||||
|
||||
public static function make($route, $name = '', $request_method = ['GET', 'POST'], $params = []): static
|
||||
|
||||
@ -21,18 +21,14 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
class Middleware extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
* @Required()
|
||||
* @param string[] $params
|
||||
*/
|
||||
public string $name;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public array $params = [];
|
||||
|
||||
public function __construct($name, $params = [])
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->params = $params;
|
||||
public function __construct(
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public $name,
|
||||
public array $params = []
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,59 +22,13 @@ use ZM\Exception\ZMKnownException;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||
class BotCommand extends AnnotationBase implements Level
|
||||
{
|
||||
public string $name = '';
|
||||
|
||||
public string $match = '';
|
||||
|
||||
public string $pattern = '';
|
||||
|
||||
public string $regex = '';
|
||||
|
||||
public string $start_with = '';
|
||||
|
||||
public string $end_with = '';
|
||||
|
||||
public string $keyword = '';
|
||||
|
||||
/** @var string[] */
|
||||
public array $alias = [];
|
||||
|
||||
public string $message_type = '';
|
||||
|
||||
public string $user_id = '';
|
||||
|
||||
public string $group_id = '';
|
||||
|
||||
public int $level = 20;
|
||||
|
||||
private array $arguments = [];
|
||||
|
||||
public function __construct(
|
||||
$name = '',
|
||||
$match = '',
|
||||
$pattern = '',
|
||||
$regex = '',
|
||||
$start_with = '',
|
||||
$end_with = '',
|
||||
$keyword = '',
|
||||
$alias = [],
|
||||
$message_type = '',
|
||||
$user_id = '',
|
||||
$group_id = '',
|
||||
$level = 20
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->match = $match;
|
||||
$this->pattern = $pattern;
|
||||
$this->regex = $regex;
|
||||
$this->start_with = $start_with;
|
||||
$this->end_with = $end_with;
|
||||
$this->keyword = $keyword;
|
||||
$this->alias = $alias;
|
||||
$this->message_type = $message_type;
|
||||
$this->user_id = $user_id;
|
||||
$this->group_id = $group_id;
|
||||
$this->level = $level;
|
||||
/**
|
||||
* @param string[] $alias
|
||||
*/
|
||||
public function __construct(public $name = '', public $match = '', public $pattern = '', public $regex = '', public $start_with = '', public $end_with = '', public $keyword = '', public $alias = [], public $message_type = '', public $user_id = '', public $group_id = '', public $level = 20)
|
||||
{
|
||||
}
|
||||
|
||||
public static function make(
|
||||
@ -95,7 +49,6 @@ class BotCommand extends AnnotationBase implements Level
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws InvalidArgumentException
|
||||
* @throws ZMKnownException
|
||||
*/
|
||||
|
||||
@ -19,32 +19,8 @@ use ZM\Annotation\AnnotationBase;
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class BotEvent extends AnnotationBase
|
||||
{
|
||||
public ?string $type;
|
||||
|
||||
public ?string $detail_type;
|
||||
|
||||
public ?string $impl;
|
||||
|
||||
public ?string $platform;
|
||||
|
||||
public ?string $self_id;
|
||||
|
||||
public ?string $sub_type;
|
||||
|
||||
public function __construct(
|
||||
?string $type = null,
|
||||
?string $detail_type = null,
|
||||
?string $impl = null,
|
||||
?string $platform = null,
|
||||
?string $self_id = null,
|
||||
?string $sub_type = null
|
||||
) {
|
||||
$this->type = $type;
|
||||
$this->detail_type = $detail_type;
|
||||
$this->impl = $impl;
|
||||
$this->platform = $platform;
|
||||
$this->self_id = $self_id;
|
||||
$this->sub_type = $sub_type;
|
||||
public function __construct(public ?string $type = null, public ?string $detail_type = null, public ?string $impl = null, public ?string $platform = null, public ?string $self_id = null, public ?string $sub_type = null)
|
||||
{
|
||||
}
|
||||
|
||||
public static function make(
|
||||
|
||||
@ -20,25 +20,8 @@ use ZM\Exception\ZMKnownException;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_ALL)]
|
||||
class CommandArgument extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $name;
|
||||
|
||||
public string $description = '';
|
||||
|
||||
public string $type = 'string';
|
||||
|
||||
public bool $required = false;
|
||||
|
||||
public string $prompt = '';
|
||||
|
||||
public string $default = '';
|
||||
|
||||
public int $timeout = 60;
|
||||
|
||||
public int $error_prompt_policy = 1;
|
||||
|
||||
/**
|
||||
* @param string $name 参数名称(可以是中文)
|
||||
* @param string $description 参数描述(默认为空)
|
||||
@ -49,23 +32,19 @@ class CommandArgument extends AnnotationBase implements ErgodicAnnotation
|
||||
* @throws InvalidArgumentException|ZMKnownException
|
||||
*/
|
||||
public function __construct(
|
||||
string $name,
|
||||
string $description = '',
|
||||
/**
|
||||
* @Required()
|
||||
*/
|
||||
public string $name,
|
||||
public string $description = '',
|
||||
string $type = 'string',
|
||||
bool $required = false,
|
||||
string $prompt = '',
|
||||
string $default = '',
|
||||
int $timeout = 60,
|
||||
int $error_prompt_policy = 1
|
||||
public bool $required = false,
|
||||
public string $prompt = '',
|
||||
public string $default = '',
|
||||
public int $timeout = 60,
|
||||
public int $error_prompt_policy = 1
|
||||
) {
|
||||
$this->name = $name;
|
||||
$this->description = $description;
|
||||
$this->type = $this->fixTypeName($type);
|
||||
$this->required = $required;
|
||||
$this->prompt = $prompt;
|
||||
$this->default = $default;
|
||||
$this->timeout = $timeout;
|
||||
$this->error_prompt_policy = $error_prompt_policy;
|
||||
if ($this->type === 'bool') {
|
||||
if ($this->default === '') {
|
||||
$this->default = 'yes';
|
||||
|
||||
@ -11,7 +11,7 @@ class CheckConfigCommand extends Command
|
||||
{
|
||||
use SourceLoadModeOnly;
|
||||
|
||||
private $need_update = false;
|
||||
private bool $need_update = false;
|
||||
|
||||
protected function handle(): int
|
||||
{
|
||||
|
||||
@ -130,9 +130,7 @@ class InitCommand extends Command
|
||||
// TODO: 优化代码,避免在循环中使用 array_merge 以减少资源消耗
|
||||
$files = array_merge($files, glob($this->getVendorPath($pattern), GLOB_BRACE));
|
||||
}
|
||||
return array_map(function ($file) {
|
||||
return str_replace($this->getVendorPath(''), '', $file);
|
||||
}, $files);
|
||||
return array_map(fn ($file) => str_replace($this->getVendorPath(''), '', $file), $files);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -143,7 +143,7 @@ class ProxyServerCommand extends Command
|
||||
$ip = 0;
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
// var_dump(ord($tmp[$i]));
|
||||
$ip += ord($tmp[$i]) * pow(256, 3 - $i);
|
||||
$ip += ord($tmp[$i]) * 256 ** (3 - $i);
|
||||
}
|
||||
$request['dest_addr'] = long2ip($ip);
|
||||
$offset += 4;
|
||||
@ -308,6 +308,7 @@ class ProxyServerCommand extends Command
|
||||
|
||||
public function udpWorkerOnMessage($udp_connection, $data, &$worker)
|
||||
{
|
||||
$addr = [];
|
||||
logger()->debug('send:' . bin2hex($data));
|
||||
$request = [];
|
||||
$offset = 0;
|
||||
@ -326,7 +327,7 @@ class ProxyServerCommand extends Command
|
||||
$tmp = substr($data, $offset, 4);
|
||||
$ip = 0;
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$ip += ord($tmp[$i]) * pow(256, 3 - $i);
|
||||
$ip += ord($tmp[$i]) * 256 ** (3 - $i);
|
||||
}
|
||||
$request['dest_addr'] = long2ip($ip);
|
||||
$offset += 4;
|
||||
@ -412,15 +413,11 @@ class ProxyServerCommand extends Command
|
||||
$this->config['auth'] = [0 => true];
|
||||
$type = $input->getOption('type') ?? 'http';
|
||||
logger()->notice('Proxy server started at ' . $type . '://' . $address . ':' . $port);
|
||||
switch ($type) {
|
||||
case 'http':
|
||||
$this->startHttpProxy($address, $port);
|
||||
break;
|
||||
case 'socks':
|
||||
case 'socks5':
|
||||
$this->startSocksProxy($address, $port);
|
||||
break;
|
||||
}
|
||||
match ($type) {
|
||||
'http' => $this->startHttpProxy($address, $port),
|
||||
'socks', 'socks5' => $this->startSocksProxy($address, $port),
|
||||
default => 0,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -464,7 +461,7 @@ class ProxyServerCommand extends Command
|
||||
* @param string $address 地址
|
||||
* @param int|string $port 端口
|
||||
*/
|
||||
private function startSocksProxy(string $address, $port)
|
||||
private function startSocksProxy(string $address, int|string $port)
|
||||
{
|
||||
define('STAGE_INIT', 0);
|
||||
define('STAGE_AUTH', 1);
|
||||
|
||||
@ -21,9 +21,7 @@ class ServerStartCommand extends ServerCommand
|
||||
{
|
||||
$cmd = new self();
|
||||
$cmd->configure();
|
||||
return array_map(function ($x) {
|
||||
return $x->getDefault();
|
||||
}, $cmd->getDefinition()->getOptions());
|
||||
return array_map(fn ($x) => $x->getDefault(), $cmd->getDefinition()->getOptions());
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
|
||||
@ -33,7 +33,7 @@ class ServerStopCommand extends ServerCommand
|
||||
$pid = file_get_contents($file_path . '/' . $file);
|
||||
Process::kill((int) $pid, SIGKILL);
|
||||
} elseif ($file === 'master.json') {
|
||||
$json = json_decode(file_get_contents($file_path . '/' . $file), true);
|
||||
$json = json_decode(file_get_contents($file_path . '/' . $file), true, 512, JSON_THROW_ON_ERROR);
|
||||
Process::kill($json['pid'], SIGKILL);
|
||||
}
|
||||
unlink($file_path . '/' . $file);
|
||||
|
||||
@ -60,7 +60,7 @@ class ZMConfig
|
||||
/**
|
||||
* @var null|ConfigTracer 配置跟踪器
|
||||
*/
|
||||
private ?ConfigTracer $tracer;
|
||||
private ?ConfigTracer $tracer = null;
|
||||
|
||||
/**
|
||||
* 构造配置实例
|
||||
@ -159,7 +159,7 @@ class ZMConfig
|
||||
*
|
||||
* @return null|array|mixed
|
||||
*/
|
||||
public function get(string $key, $default = null)
|
||||
public function get(string $key, mixed $default = null)
|
||||
{
|
||||
return $this->holder->get($key, $default);
|
||||
}
|
||||
@ -174,7 +174,7 @@ class ZMConfig
|
||||
* @param array|string $key 配置项名称,可使用.访问数组
|
||||
* @param mixed $value 要写入的值,传入 null 会进行删除
|
||||
*/
|
||||
public function set($key, $value = null): void
|
||||
public function set(array|string $key, mixed $value = null): void
|
||||
{
|
||||
$keys = is_array($key) ? $key : [$key => $value];
|
||||
foreach ($keys as $i_key => $i_val) {
|
||||
@ -294,7 +294,7 @@ class ZMConfig
|
||||
// 2. 文件名.环境:如 test.development,此时加载类型为 environment
|
||||
// 3. 文件名.patch:如 test.patch,此时加载类型为 patch
|
||||
// 至于其他的格式,则为未定义行为
|
||||
if (strpos($name, '.') === false) {
|
||||
if (!str_contains($name, '.')) {
|
||||
return 'default';
|
||||
}
|
||||
$name_and_env = explode('.', $name);
|
||||
|
||||
@ -19,7 +19,7 @@ use ZM\Store\FileSystem;
|
||||
*/
|
||||
final class ConsoleApplication extends Application
|
||||
{
|
||||
private static $obj;
|
||||
private static ?ConsoleApplication $obj = null;
|
||||
|
||||
public function __construct(string $name = 'zhamao-framework')
|
||||
{
|
||||
|
||||
@ -12,12 +12,11 @@ class BoundMethod
|
||||
* 调用指定闭包、类方法并注入依赖
|
||||
*
|
||||
* @param Container $container
|
||||
* @param callable|string $callback
|
||||
* @return mixed
|
||||
* @throws EntryResolutionException|\ReflectionException
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function call(ContainerInterface $container, $callback, array $parameters = [], string $default_method = null)
|
||||
public static function call(ContainerInterface $container, callable|string $callback, array $parameters = [], string $default_method = null)
|
||||
{
|
||||
if (is_string($callback) && !$default_method && method_exists($callback, '__invoke')) {
|
||||
$default_method = '__invoke';
|
||||
@ -41,10 +40,9 @@ class BoundMethod
|
||||
/**
|
||||
* Get all dependencies for a given method.
|
||||
*
|
||||
* @param callable|string $callback
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected static function getMethodDependencies(ContainerInterface $container, $callback, array $parameters = []): array
|
||||
protected static function getMethodDependencies(ContainerInterface $container, callable|string $callback, array $parameters = []): array
|
||||
{
|
||||
$dependencies = [];
|
||||
|
||||
|
||||
@ -10,47 +10,42 @@ use ZM\Utils\ReflectionUtil;
|
||||
|
||||
trait ContainerTrait
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $shared = [];
|
||||
protected array $shared = [];
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
protected $build_stack = [];
|
||||
protected array $build_stack = [];
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
protected $with = [];
|
||||
protected array $with = [];
|
||||
|
||||
/**
|
||||
* 日志前缀
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $log_prefix;
|
||||
protected string $log_prefix;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private static $bindings = [];
|
||||
private static array $bindings = [];
|
||||
|
||||
/**
|
||||
* @var object[]
|
||||
*/
|
||||
private static $instances = [];
|
||||
private static array $instances = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private static $aliases = [];
|
||||
private static array $aliases = [];
|
||||
|
||||
/**
|
||||
* @var \Closure[][]
|
||||
*/
|
||||
private static $extenders = [];
|
||||
private static array $extenders = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -188,7 +183,7 @@ trait ContainerTrait
|
||||
* @param mixed $instance 实例
|
||||
* @return mixed
|
||||
*/
|
||||
public function instance(string $abstract, $instance)
|
||||
public function instance(string $abstract, mixed $instance)
|
||||
{
|
||||
if (isset(self::$instances[$abstract])) {
|
||||
return self::$instances[$abstract];
|
||||
@ -211,9 +206,7 @@ trait ContainerTrait
|
||||
*/
|
||||
public function factory(string $abstract): \Closure
|
||||
{
|
||||
return function () use ($abstract) {
|
||||
return $this->make($abstract);
|
||||
};
|
||||
return fn () => $this->make($abstract);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +306,7 @@ trait ContainerTrait
|
||||
* @return mixed
|
||||
* @throws EntryResolutionException
|
||||
*/
|
||||
public function build($concrete)
|
||||
public function build(\Closure|string $concrete)
|
||||
{
|
||||
// 如果传入的是闭包,则直接执行并返回
|
||||
if ($concrete instanceof \Closure) {
|
||||
@ -363,7 +356,7 @@ trait ContainerTrait
|
||||
* @param null|string $default_method 默认方法
|
||||
* @return mixed
|
||||
*/
|
||||
public function call($callback, array $parameters = [], string $default_method = null)
|
||||
public function call(callable|string $callback, array $parameters = [], string $default_method = null)
|
||||
{
|
||||
if ($this->shouldLog()) {
|
||||
if (count($parameters)) {
|
||||
@ -446,7 +439,7 @@ trait ContainerTrait
|
||||
*/
|
||||
public function getLogPrefix(): string
|
||||
{
|
||||
return ($this->log_prefix ?: '[WorkerContainer(U)]') . ' ';
|
||||
return ($this->log_prefix ?? '[WorkerContainer(U)]') . ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -674,10 +667,9 @@ trait ContainerTrait
|
||||
/**
|
||||
* 获取类名的实际类型
|
||||
*
|
||||
* @param string $abstract 类或接口名
|
||||
* @return \Closure|string
|
||||
* @param string $abstract 类或接口名
|
||||
*/
|
||||
protected function getConcrete(string $abstract)
|
||||
protected function getConcrete(string $abstract): \Closure|string
|
||||
{
|
||||
if (isset(self::$bindings[$abstract])) {
|
||||
return self::$bindings[$abstract]['concrete'];
|
||||
@ -692,7 +684,7 @@ trait ContainerTrait
|
||||
* @param mixed $concrete 实际类型
|
||||
* @param string $abstract 类或接口名
|
||||
*/
|
||||
protected function isBuildable($concrete, string $abstract): bool
|
||||
protected function isBuildable(mixed $concrete, string $abstract): bool
|
||||
{
|
||||
return $concrete === $abstract || $concrete instanceof \Closure;
|
||||
}
|
||||
|
||||
@ -14,10 +14,10 @@ class EventProvider implements SortedProviderInterface
|
||||
/**
|
||||
* @var array<string, array<array<int, callable>>> 已注册的事件监听器
|
||||
*/
|
||||
private static $_events = [];
|
||||
private static array $_events = [];
|
||||
|
||||
/** @var array @phpstan-ignore-next-line */
|
||||
private static $_event_map = [];
|
||||
private static array $_event_map = [];
|
||||
|
||||
/**
|
||||
* 添加事件监听器
|
||||
@ -30,15 +30,15 @@ class EventProvider implements SortedProviderInterface
|
||||
{
|
||||
if (is_object($event)) { // 传入对象时必须带 class 和 method 属性,这时将忽略 callback 参数
|
||||
if (property_exists($event, 'class') && property_exists($event, 'method')) {
|
||||
self::$_events[get_class($event)][] = [$level, [resolve($event->class), $event->method]];
|
||||
self::$_events[$event::class][] = [$level, [resolve($event->class), $event->method]];
|
||||
self::$_event_map[$event->class][$event->method][] = $event;
|
||||
} elseif (is_array($callback) && is_object($callback[0] ?? '') && is_string($callback[1] ?? null)) {
|
||||
// 如果没有上面两个属性,则可能是回调函数是一个数组,如果是这样,则可以直接使用回调函数
|
||||
self::$_event_map[get_class($callback[0])][$callback[1]][] = $event;
|
||||
$event->class = get_class($callback[0]);
|
||||
self::$_event_map[$callback[0]::class][$callback[1]][] = $event;
|
||||
$event->class = $callback[0]::class;
|
||||
$event->method = $callback[1];
|
||||
}
|
||||
$this->sortEvents(get_class($event));
|
||||
$this->sortEvents($event::class);
|
||||
} elseif (is_string($event)) {
|
||||
self::$_events[$event][] = [$level, $callback];
|
||||
$this->sortEvents($event);
|
||||
@ -66,18 +66,14 @@ class EventProvider implements SortedProviderInterface
|
||||
*/
|
||||
public function getListenersForEvent(object $event): iterable
|
||||
{
|
||||
return self::getEventListeners(method_exists($event, 'getName') ? $event->getName() : get_class($event));
|
||||
return $this->getEventListeners(method_exists($event, 'getName') ? $event->getName() : $event::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 排序事件
|
||||
*
|
||||
* @param string|\Stringable $name
|
||||
*/
|
||||
private function sortEvents($name)
|
||||
private function sortEvents(string|\Stringable $name)
|
||||
{
|
||||
usort(self::$_events[$name], function ($a, $b) {
|
||||
return $a[0] <= $b[0] ? 1 : -1;
|
||||
});
|
||||
usort(self::$_events[$name], fn ($a, $b) => $a[0] <= $b[0] ? 1 : -1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,10 +17,8 @@ class SignalListener
|
||||
|
||||
/**
|
||||
* 用于记录 Ctrl+C 的次数
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private static $manager_kill_time = 0;
|
||||
private static int $manager_kill_time = 0;
|
||||
|
||||
/**
|
||||
* 开启 Worker 进程的 SIGINT 监听
|
||||
|
||||
@ -181,9 +181,7 @@ class WorkerEventListener
|
||||
private function dispatchInit(): void
|
||||
{
|
||||
$handler = new AnnotationHandler(Init::class);
|
||||
$handler->setRuleCallback(function (Init $anno) {
|
||||
return $anno->worker === -1 || $anno->worker === ProcessManager::getProcessId();
|
||||
});
|
||||
$handler->setRuleCallback(fn (Init $anno) => $anno->worker === -1 || $anno->worker === ProcessManager::getProcessId());
|
||||
$handler->handleAll();
|
||||
}
|
||||
|
||||
|
||||
@ -6,11 +6,8 @@ namespace ZM\Exception;
|
||||
|
||||
class InterruptException extends ZMException
|
||||
{
|
||||
public $return_var;
|
||||
|
||||
public function __construct($return_var = null, $message = '', $code = 0, \Throwable $previous = null)
|
||||
public function __construct(public $return_var = null, $message = '', $code = 0, \Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, '', $code, $previous);
|
||||
$this->return_var = $return_var;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ use ZM\Exception\SingletonViolationException;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Logger\TablePrinter;
|
||||
use ZM\Process\ProcessStateManager;
|
||||
use ZM\Store\FileSystem;
|
||||
use ZM\Utils\EasterEgg;
|
||||
|
||||
/**
|
||||
@ -173,10 +174,8 @@ class Framework
|
||||
|
||||
/**
|
||||
* 获取驱动
|
||||
*
|
||||
* @return Driver|SwooleDriver|WorkermanDriver
|
||||
*/
|
||||
public function getDriver()
|
||||
public function getDriver(): Driver
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
@ -242,7 +241,7 @@ class Framework
|
||||
|
||||
// 框架多进程依赖
|
||||
if (defined('ZM_STATE_DIR') && !is_dir(ZM_STATE_DIR)) {
|
||||
mkdir(ZM_STATE_DIR);
|
||||
FileSystem::createDir(ZM_STATE_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +407,7 @@ class Framework
|
||||
logger()->emergency('代码解析错误!');
|
||||
exit(1);
|
||||
}
|
||||
$json = json_decode($r, true);
|
||||
$json = json_decode($r, true, 512, JSON_THROW_ON_ERROR);
|
||||
if (!is_array($json)) {
|
||||
logger()->error(zm_internal_errcode('E00012') . '解析 @OnSetup 时发生错误,请检查代码!');
|
||||
return;
|
||||
|
||||
@ -14,22 +14,22 @@ class MiddlewareHandler
|
||||
/**
|
||||
* @var array 存储中间件的
|
||||
*/
|
||||
protected $middlewares = [];
|
||||
protected array $middlewares = [];
|
||||
|
||||
/**
|
||||
* @var array 存储注册中间件的类和方法
|
||||
*/
|
||||
protected $reg_map = [];
|
||||
protected array $reg_map = [];
|
||||
|
||||
/**
|
||||
* @var array 用于将中间件名称压栈
|
||||
*/
|
||||
protected $stack = [];
|
||||
protected array $stack = [];
|
||||
|
||||
/**
|
||||
* @var array 用于将正在运行的中间件压栈
|
||||
*/
|
||||
protected $callable_stack = [];
|
||||
protected array $callable_stack = [];
|
||||
|
||||
public function registerBefore(string $name, callable $callback)
|
||||
{
|
||||
@ -44,7 +44,7 @@ class MiddlewareHandler
|
||||
&& isset($this->middlewares[$name]['before']) // 且存在before
|
||||
&& is_array($this->middlewares[$name]['before']) // 且before也是数组类型callback
|
||||
&& is_object($this->middlewares[$name]['before'][0]) // 且before类型也为动态调用
|
||||
&& get_class($this->middlewares[$name]['before'][0]) === get_class($callback[0]) // 且before和after在一个类
|
||||
&& $this->middlewares[$name]['before'][0]::class === $callback[0]::class // 且before和after在一个类
|
||||
) {
|
||||
// 那么就把after的对象替换为和before同一个
|
||||
$callback[0] = $this->middlewares[$name]['before'][0];
|
||||
@ -173,7 +173,7 @@ class MiddlewareHandler
|
||||
}
|
||||
if (is_array($callback) && count($callback) === 2) {
|
||||
// 活性调用,根据组合名称来判断
|
||||
return (is_object($callback[0]) ? get_class($callback[0]) : $callback[0]) . '::' . $callback[1];
|
||||
return (is_object($callback[0]) ? $callback[0]::class : $callback[0]) . '::' . $callback[1];
|
||||
}
|
||||
if (is_string($callback)) {
|
||||
return $callback;
|
||||
|
||||
@ -18,8 +18,7 @@ class Pipeline
|
||||
/**
|
||||
* 向管道发送数据
|
||||
*
|
||||
* @param mixed $value 数据
|
||||
* @return $this
|
||||
* @param mixed $value 数据
|
||||
*/
|
||||
public function send(mixed $value): Pipeline
|
||||
{
|
||||
@ -30,8 +29,7 @@ class Pipeline
|
||||
/**
|
||||
* 指定要过的中间件列表
|
||||
*
|
||||
* @param array $middlewares 要过的中间件(或者叫兼容管道的中间件也行)列表
|
||||
* @return $this
|
||||
* @param array $middlewares 要过的中间件(或者叫兼容管道的中间件也行)列表
|
||||
*/
|
||||
public function through(array $middlewares): Pipeline
|
||||
{
|
||||
|
||||
@ -12,11 +12,10 @@ class ProcessStateManager
|
||||
public static array $process_mode = [];
|
||||
|
||||
/**
|
||||
* @param null|int|string $id_or_name
|
||||
* @throws ZMKnownException
|
||||
* @internal
|
||||
*/
|
||||
public static function removeProcessState(int $type, $id_or_name = null)
|
||||
public static function removeProcessState(int $type, int|string $id_or_name = null)
|
||||
{
|
||||
switch ($type) {
|
||||
case ZM_PROCESS_MASTER:
|
||||
@ -64,12 +63,11 @@ class ProcessStateManager
|
||||
/**
|
||||
* 用于框架内部获取多进程运行状态的函数
|
||||
*
|
||||
* @param mixed $id_or_name
|
||||
* @return false|int|mixed
|
||||
* @throws ZMKnownException
|
||||
* @internal
|
||||
*/
|
||||
public static function getProcessState(int $type, $id_or_name = null)
|
||||
public static function getProcessState(int $type, mixed $id_or_name = null)
|
||||
{
|
||||
$file = ZM_STATE_DIR;
|
||||
switch ($type) {
|
||||
@ -78,10 +76,7 @@ class ProcessStateManager
|
||||
return false;
|
||||
}
|
||||
$json = json_decode(file_get_contents(zm_dir($file . '/master.json')), true);
|
||||
if ($json !== null) {
|
||||
return $json;
|
||||
}
|
||||
return false;
|
||||
return $json ?? false;
|
||||
case ZM_PROCESS_MANAGER:
|
||||
if (!file_exists(zm_dir($file . '/manager.pid'))) {
|
||||
return false;
|
||||
@ -119,10 +114,9 @@ class ProcessStateManager
|
||||
/**
|
||||
* 将各进程的pid写入文件,以备后续崩溃及僵尸进程处理使用
|
||||
*
|
||||
* @param int|string $pid
|
||||
* @internal
|
||||
*/
|
||||
public static function saveProcessState(int $type, $pid, array $data = [])
|
||||
public static function saveProcessState(int $type, int|string $pid, array $data = [])
|
||||
{
|
||||
switch ($type) {
|
||||
case ZM_PROCESS_MASTER:
|
||||
|
||||
@ -12,7 +12,7 @@ use Doctrine\DBAL\ParameterType;
|
||||
class DBConnection implements Connection
|
||||
{
|
||||
/** @var \PDO */
|
||||
private $conn;
|
||||
private object $conn;
|
||||
|
||||
private $pool_name;
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ class DBPool
|
||||
/**
|
||||
* @var array<string, SwooleObjectPool|WorkermanObjectPool> 连接池列表
|
||||
*/
|
||||
private static $pools = [];
|
||||
private static array $pools = [];
|
||||
|
||||
/**
|
||||
* 通过配置文件创建一个 MySQL 连接池
|
||||
@ -68,10 +68,9 @@ class DBPool
|
||||
/**
|
||||
* 获取一个数据库连接池
|
||||
*
|
||||
* @param string $name 连接池名称
|
||||
* @return SwooleObjectPool|WorkermanObjectPool
|
||||
* @param string $name 连接池名称
|
||||
*/
|
||||
public static function pool(string $name)
|
||||
public static function pool(string $name): PoolInterface
|
||||
{
|
||||
if (!isset(self::$pools[$name]) && count(self::$pools) !== 1) {
|
||||
throw new \RuntimeException("Pool {$name} not found");
|
||||
|
||||
@ -9,7 +9,7 @@ use ZM\Store\Database\DBException as DbException;
|
||||
|
||||
class DBQueryBuilder extends QueryBuilder
|
||||
{
|
||||
private $wrapper;
|
||||
private DBWrapper $wrapper;
|
||||
|
||||
public function __construct(DBWrapper $wrapper)
|
||||
{
|
||||
@ -18,10 +18,9 @@ class DBQueryBuilder extends QueryBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DBStatementWrapper|int
|
||||
* @throws DbException
|
||||
*/
|
||||
public function execute()
|
||||
public function execute(): DBStatementWrapper|int
|
||||
{
|
||||
if ($this->getType() === self::SELECT) {
|
||||
return $this->wrapper->executeQuery($this->getSQL(), $this->getParameters(), $this->getParameterTypes());
|
||||
|
||||
@ -13,12 +13,8 @@ use Doctrine\DBAL\ParameterType;
|
||||
|
||||
class DBStatement implements \IteratorAggregate, Statement
|
||||
{
|
||||
/** @var \PDOStatement */
|
||||
private $statement;
|
||||
|
||||
public function __construct($obj)
|
||||
public function __construct(private \PDOStatement $statement)
|
||||
{
|
||||
$this->statement = $obj;
|
||||
}
|
||||
|
||||
public function closeCursor()
|
||||
|
||||
@ -14,11 +14,8 @@ use Doctrine\DBAL\ForwardCompatibility\Result;
|
||||
|
||||
class DBStatementWrapper
|
||||
{
|
||||
public ?Result $stmt;
|
||||
|
||||
public function __construct(?Result $stmt)
|
||||
public function __construct(public ?Result $stmt)
|
||||
{
|
||||
$this->stmt = $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -22,7 +22,7 @@ class DBWrapper
|
||||
{
|
||||
try {
|
||||
$db_list = config()->get('global.database');
|
||||
if (isset($db_list[$name]) || count($db_list) === 1) {
|
||||
if (isset($db_list[$name]) || (is_countable($db_list) ? count($db_list) : 0) === 1) {
|
||||
if ($name === '') {
|
||||
$name = array_key_first($db_list);
|
||||
}
|
||||
@ -66,10 +66,9 @@ class DBWrapper
|
||||
|
||||
/**
|
||||
* wrapper method
|
||||
* @return array|false
|
||||
* @throws DBException
|
||||
*/
|
||||
public function fetchAssociative(string $query, array $params = [], array $types = [])
|
||||
public function fetchAssociative(string $query, array $params = [], array $types = []): array|false
|
||||
{
|
||||
try {
|
||||
return $this->connection->fetchAssociative($query, $params, $types);
|
||||
@ -80,10 +79,9 @@ class DBWrapper
|
||||
|
||||
/**
|
||||
* wrapper method
|
||||
* @return array|false
|
||||
* @throws DBException
|
||||
*/
|
||||
public function fetchNumeric(string $query, array $params = [], array $types = [])
|
||||
public function fetchNumeric(string $query, array $params = [], array $types = []): array|false
|
||||
{
|
||||
try {
|
||||
return $this->connection->fetchNumeric($query, $params, $types);
|
||||
@ -182,10 +180,9 @@ class DBWrapper
|
||||
|
||||
/**
|
||||
* wrapper method
|
||||
* @param mixed $value
|
||||
* @param null|int|string|Type $type
|
||||
*/
|
||||
public function quote($value, $type = ParameterType::STRING)
|
||||
public function quote(mixed $value, $type = ParameterType::STRING)
|
||||
{
|
||||
return $this->connection->quote($value, $type);
|
||||
}
|
||||
@ -414,7 +411,7 @@ class DBWrapper
|
||||
* @return int|string the number of affected rows
|
||||
* @throws DBException
|
||||
*/
|
||||
public function executeStatement(string $sql, array $params = [], array $types = [])
|
||||
public function executeStatement(string $sql, array $params = [], array $types = []): int|string
|
||||
{
|
||||
try {
|
||||
return $this->connection->executeStatement($sql, $params, $types);
|
||||
@ -436,7 +433,7 @@ class DBWrapper
|
||||
* @param null|string $name name of the sequence object from which the ID should be returned
|
||||
* @return false|int|string a string representation of the last inserted ID
|
||||
*/
|
||||
public function lastInsertId(?string $name = null)
|
||||
public function lastInsertId(?string $name = null): false|int|string
|
||||
{
|
||||
return $this->connection->lastInsertId($name);
|
||||
}
|
||||
@ -600,13 +597,10 @@ class DBWrapper
|
||||
*/
|
||||
private function getConnectionClass(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case 'mysql':
|
||||
return MySQLDriver::class;
|
||||
case 'sqlite':
|
||||
return SQLiteDriver::class;
|
||||
default:
|
||||
throw new DBException('Unknown database type: ' . $type);
|
||||
}
|
||||
return match ($type) {
|
||||
'mysql' => MySQLDriver::class,
|
||||
'sqlite' => SQLiteDriver::class,
|
||||
default => throw new DBException('Unknown database type: ' . $type),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,14 +11,13 @@ class FileSystem
|
||||
/**
|
||||
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
|
||||
*
|
||||
* @param string $dir 目录
|
||||
* @param bool $recursive 是否递归扫描子目录
|
||||
* @param bool|string $relative 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录
|
||||
* @param bool $include_dir 非递归模式下,是否包含目录
|
||||
* @return array|false
|
||||
* @param string $dir 目录
|
||||
* @param bool $recursive 是否递归扫描子目录
|
||||
* @param bool|string $relative 是否返回相对目录,如果为true则返回相对目录,如果为false则返回绝对目录
|
||||
* @param bool $include_dir 非递归模式下,是否包含目录
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function scanDirFiles(string $dir, bool $recursive = true, $relative = false, bool $include_dir = false)
|
||||
public static function scanDirFiles(string $dir, bool $recursive = true, bool|string $relative = false, bool $include_dir = false): array|false
|
||||
{
|
||||
$dir = zm_dir($dir);
|
||||
// 不是目录不扫,直接 false 处理
|
||||
@ -114,26 +113,26 @@ class FileSystem
|
||||
* @param bool|string $return_path_value 是否返回文件路径,返回文件路径的话传入字符串
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getClassesPsr4(string $dir, string $base_namespace, $rule = null, $return_path_value = false): array
|
||||
public static function getClassesPsr4(string $dir, string $base_namespace, mixed $rule = null, bool|string $return_path_value = false): array
|
||||
{
|
||||
// 预先读取下composer的file列表
|
||||
$composer = ZMUtil::getComposerMetadata();
|
||||
$classes = [];
|
||||
// 扫描目录,使用递归模式,相对路径模式,因为下面此路径要用作转换成namespace
|
||||
$files = FileSystem::scanDirFiles($dir, true, true);
|
||||
$files = self::scanDirFiles($dir, true, true);
|
||||
foreach ($files as $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if (($pathinfo['extension'] ?? '') == 'php') {
|
||||
$path = rtrim($dir, '/') . '/' . rtrim($pathinfo['dirname'], './') . '/' . $pathinfo['basename'];
|
||||
|
||||
// 过滤不包含类的文件
|
||||
$tokens = token_get_all(file_get_contents($path));
|
||||
$tokens = \PhpToken::tokenize(file_get_contents($path));
|
||||
$found = false;
|
||||
foreach ($tokens as $token) {
|
||||
if (!is_array($token)) {
|
||||
if (!$token instanceof \PhpToken) {
|
||||
continue;
|
||||
}
|
||||
if ($token[0] === T_CLASS) {
|
||||
if ($token->is(T_CLASS)) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -8,9 +8,9 @@ use ZM\Exception\ZMKnownException;
|
||||
|
||||
class FileLock
|
||||
{
|
||||
private static $lock_file_handle = [];
|
||||
private static array $lock_file_handle = [];
|
||||
|
||||
private static $name_hash = [];
|
||||
private static array $name_hash = [];
|
||||
|
||||
/**
|
||||
* 基于文件的锁,适用于跨进程操作资源用的
|
||||
@ -19,7 +19,7 @@ class FileLock
|
||||
*/
|
||||
public static function lock(string $name)
|
||||
{
|
||||
self::$name_hash[$name] = self::$name_hash[$name] ?? md5($name);
|
||||
self::$name_hash[$name] ??= md5($name);
|
||||
$lock_file = zm_dir(TMP_DIR . '/.zm_' . zm_instance_id() . self::$name_hash[$name] . '.lock');
|
||||
self::$lock_file_handle[$name] = fopen($lock_file, 'w');
|
||||
if (self::$lock_file_handle[$name] === false) {
|
||||
|
||||
@ -37,7 +37,7 @@ class ConnectionUtil
|
||||
// 这里下面为连接准入,允许接入反向 WS
|
||||
if (ProcessStateManager::$process_mode['worker'] > 1) {
|
||||
// 文件名格式为 .WS{fd}.{pid},文件内容是 impl 名称的 JSON 格式
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()), json_encode($handle));
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()), json_encode($handle, JSON_THROW_ON_ERROR));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -53,7 +53,7 @@ class ConnectionUtil
|
||||
// 这里下面为连接准入,允许接入反向 WS
|
||||
if (ProcessStateManager::$process_mode['worker'] > 1) {
|
||||
// 文件名格式为 .WS{fd}.{pid},文件内容是 impl 名称的 JSON 格式
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()), json_encode(self::$connection_handles[$fd]));
|
||||
file_put_contents(zm_dir(ZM_STATE_DIR . '/.WS' . $fd . '.' . ProcessManager::getProcessId()), json_encode(self::$connection_handles[$fd], JSON_THROW_ON_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,10 +21,7 @@ use ZM\Store\FileSystem;
|
||||
*/
|
||||
class HttpUtil
|
||||
{
|
||||
/**
|
||||
* @var RouteCollection
|
||||
*/
|
||||
private static $routes;
|
||||
private static ?RouteCollection $routes = null;
|
||||
|
||||
/**
|
||||
* 解析 Uri,用于匹配路由用的
|
||||
@ -42,10 +39,10 @@ class HttpUtil
|
||||
// 使用UrlMatcher进行匹配Url
|
||||
$matcher = new UrlMatcher(static::getRouteCollection(), $context);
|
||||
$matched = $matcher->match($request->getUri()->getPath());
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
} catch (ResourceNotFoundException) {
|
||||
// 路由找不到会抛出异常,我们不需要这个异常,转换为状态码
|
||||
return ZM_ERR_ROUTE_NOT_FOUND;
|
||||
} catch (MethodNotAllowedException $e) {
|
||||
} catch (MethodNotAllowedException) {
|
||||
// 路由匹配到了,但该路由不能使用该方法,所以返回状态码(路由不允许)
|
||||
return ZM_ERR_ROUTE_METHOD_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
@ -43,16 +43,14 @@ class ReflectionUtil
|
||||
|
||||
/**
|
||||
* 将传入变量转换为字符串
|
||||
*
|
||||
* @param mixed $var
|
||||
*/
|
||||
public static function variableToString($var): string
|
||||
public static function variableToString(mixed $var): string
|
||||
{
|
||||
switch (true) {
|
||||
case is_callable($var):
|
||||
if (is_array($var)) {
|
||||
if (is_object($var[0])) {
|
||||
return get_class($var[0]) . '@' . $var[1];
|
||||
return $var[0]::class . '@' . $var[1];
|
||||
}
|
||||
return $var[0] . '::' . $var[1];
|
||||
}
|
||||
@ -60,9 +58,9 @@ class ReflectionUtil
|
||||
case is_string($var):
|
||||
return $var;
|
||||
case is_array($var):
|
||||
return 'array' . json_encode($var);
|
||||
return 'array' . json_encode($var, JSON_THROW_ON_ERROR);
|
||||
case is_object($var):
|
||||
return get_class($var);
|
||||
return $var::class;
|
||||
case is_resource($var):
|
||||
return 'resource(' . get_resource_type($var) . ')';
|
||||
case is_null($var):
|
||||
@ -83,7 +81,7 @@ class ReflectionUtil
|
||||
* @param callable|string $callback 回调
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function isNonStaticMethod($callback): bool
|
||||
public static function isNonStaticMethod(callable|array|string $callback): bool
|
||||
{
|
||||
if (is_array($callback) && is_string($callback[0])) {
|
||||
$reflection = new \ReflectionMethod($callback[0], $callback[1]);
|
||||
@ -103,7 +101,7 @@ class ReflectionUtil
|
||||
* @param callable|string $callback 回调
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public static function getCallReflector($callback): \ReflectionFunctionAbstract
|
||||
public static function getCallReflector(callable|string $callback): \ReflectionFunctionAbstract
|
||||
{
|
||||
if (is_string($callback) && str_contains($callback, '::')) {
|
||||
$callback = explode('::', $callback);
|
||||
|
||||
@ -12,6 +12,6 @@ class ZMUtil
|
||||
*/
|
||||
public static function getComposerMetadata(?string $path = null): ?array
|
||||
{
|
||||
return json_decode(file_get_contents(($path ?? SOURCE_ROOT_DIR) . '/composer.json'), true);
|
||||
return json_decode(file_get_contents(($path ?? SOURCE_ROOT_DIR) . '/composer.json'), true, 512, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,9 +94,8 @@ class ZMConfigTest extends TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider providerTestGetValue
|
||||
* @param mixed $expected
|
||||
*/
|
||||
public function testGetValue(string $key, $expected): void
|
||||
public function testGetValue(string $key, mixed $expected): void
|
||||
{
|
||||
$this->assertSame($expected, self::$config->get($key));
|
||||
}
|
||||
|
||||
@ -29,9 +29,7 @@ class PipelineTest extends TestCase
|
||||
$pipe = new Pipeline();
|
||||
$a = $pipe->send('APP')
|
||||
->through([TimerMiddleware::class])
|
||||
->then(function (string $value) {
|
||||
return $value;
|
||||
});
|
||||
->then(fn (string $value) => $value);
|
||||
$this->assertEquals('APP', $a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,9 +34,8 @@ class ReflectionUtilTest extends TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider provideTestVariableToString
|
||||
* @param mixed $variable
|
||||
*/
|
||||
public function testVariableToString($variable, string $expected): void
|
||||
public function testVariableToString(mixed $variable, string $expected): void
|
||||
{
|
||||
$this->assertSame($expected, ReflectionUtil::variableToString($variable));
|
||||
}
|
||||
@ -61,9 +60,8 @@ class ReflectionUtilTest extends TestCase
|
||||
|
||||
/**
|
||||
* @dataProvider provideTestGetCallReflector
|
||||
* @param mixed $callback
|
||||
*/
|
||||
public function testGetCallReflector($callback, \ReflectionFunctionAbstract $expected): void
|
||||
public function testGetCallReflector(mixed $callback, \ReflectionFunctionAbstract $expected): void
|
||||
{
|
||||
$this->assertEquals($expected, ReflectionUtil::getCallReflector($callback));
|
||||
}
|
||||
|
||||
@ -184,9 +184,7 @@ class ZMResultPrinter extends CliTestDoxPrinter
|
||||
|
||||
if ($this->colors) {
|
||||
$color = self::STATUS_STYLES[$result['status']]['color'] ?? '';
|
||||
$prefix = array_map(static function ($p) use ($color) {
|
||||
return Color::colorize($color, $p);
|
||||
}, self::PREFIX_DECORATED);
|
||||
$prefix = array_map(static fn ($p) => Color::colorize($color, $p), self::PREFIX_DECORATED);
|
||||
}
|
||||
|
||||
$out = '';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user