mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-17 20:54:52 +08:00
commit
14840715bc
@ -1,17 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Reload Zhamao Server" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="./zhamao server:reload && exit" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@ -1,17 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Run Zhamao Server" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="./zhamao server" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="./zhamao" />
|
||||
<option name="SCRIPT_OPTIONS" value="server" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@ -1,17 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Run watcher" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="bin/watcher" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="/bin/zsh" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@ -1,17 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Stop Zhamao Server" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="./zhamao server:stop && exit" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="" />
|
||||
<option name="SCRIPT_OPTIONS" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="false" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@ -15,6 +15,7 @@
|
||||
"require": {
|
||||
"php": "^8.0 || ^8.1",
|
||||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"doctrine/dbal": "^2.13.1",
|
||||
"dragonmantank/cron-expression": "^3.3",
|
||||
"jelix/version": "^2.0",
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
use ZM\Logger\ConsoleLogger;
|
||||
|
||||
return [
|
||||
// 设置默认的log等级
|
||||
'level' => LogLevel::INFO,
|
||||
// logger自定义回调
|
||||
'logger' => static function (string $prefix = null): LoggerInterface {
|
||||
if ($prefix) {
|
||||
$prefix = strtoupper($prefix);
|
||||
} else {
|
||||
// 在 Master 中,worker_id 将不存在
|
||||
$prefix = app()->has('worker_id') ? '#' . app('worker_id') : 'MST';
|
||||
}
|
||||
|
||||
$logger = new ConsoleLogger(config('logging.level'));
|
||||
$logger::$format = "[%date%] [%level%] [{$prefix}] %body%";
|
||||
$logger::$date_format = 'Y-m-d H:i:s';
|
||||
// 如果你喜欢旧版的日志格式,请取消下行注释
|
||||
// $logger::$date_format = 'm-d H:i:s';
|
||||
return $logger;
|
||||
},
|
||||
];
|
||||
@ -49,7 +49,7 @@ function download_file() {
|
||||
|
||||
# 安装下载内建PHP
|
||||
function install_native_php() {
|
||||
ZM_PHP_VERSION="8.0"
|
||||
ZM_PHP_VERSION="8.1"
|
||||
if [ "$ZM_DOWN_PHP_VERSION" != "" ]; then
|
||||
ZM_PHP_VERSION="$ZM_DOWN_PHP_VERSION"
|
||||
fi
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$plugin = new InstantPlugin(__DIR__);
|
||||
$plugin = new ZMPlugin(__DIR__);
|
||||
|
||||
/*
|
||||
* 发送 "测试 123",回复 "你好,123"
|
||||
|
||||
@ -7,7 +7,7 @@ use OneBot\Driver\Event\Http\HttpRequestEvent;
|
||||
require 'vendor/autoload.php';
|
||||
|
||||
// 创建框架 App
|
||||
$app = new ZM\InstantApplication();
|
||||
$app = new ZM\ZMApplication();
|
||||
// 传入自定义配置文件
|
||||
$app->patchConfig([
|
||||
'driver' => 'workerman',
|
||||
@ -32,7 +32,7 @@ $event = \ZM\Annotation\OneBot\BotEvent::make('message')->withMethod(function ()
|
||||
$app->addBotEvent($event);
|
||||
$app->addBotCommand($cmd);
|
||||
|
||||
$app->registerEvent(HttpRequestEvent::getName(), function (HttpRequestEvent $event) {
|
||||
$app->addEvent(HttpRequestEvent::getName(), function (HttpRequestEvent $event) {
|
||||
$event->withResponse(\OneBot\Http\HttpFactory::getInstance()->createResponse(503));
|
||||
});
|
||||
|
||||
|
||||
@ -12,4 +12,4 @@ class_alias(\ZM\Annotation\OneBot\BotCommand::class, 'BotCommand');
|
||||
class_alias(\ZM\Annotation\OneBot\BotEvent::class, 'BotEvent');
|
||||
class_alias(\ZM\Annotation\OneBot\CommandArgument::class, 'CommandArgument');
|
||||
class_alias(\ZM\Annotation\Closed::class, 'Closed');
|
||||
class_alias(\ZM\Plugin\InstantPlugin::class, 'InstantPlugin');
|
||||
class_alias(\ZM\Plugin\ZMPlugin::class, 'ZMPlugin');
|
||||
|
||||
@ -21,8 +21,7 @@ class AnnotationHandler
|
||||
|
||||
public const STATUS_RULE_FAILED = 4; // 判断事件执行的规则函数判定为false,所以不执行此方法
|
||||
|
||||
/** @var AnnotationBase|string */
|
||||
private $annotation_class;
|
||||
private string|AnnotationBase $annotation_class;
|
||||
|
||||
/** @var callable */
|
||||
private $rule_callback;
|
||||
@ -30,11 +29,9 @@ class AnnotationHandler
|
||||
/** @var callable */
|
||||
private $return_callback;
|
||||
|
||||
/** @var int */
|
||||
private $status = self::STATUS_NORMAL;
|
||||
private int $status = self::STATUS_NORMAL;
|
||||
|
||||
/** @var mixed */
|
||||
private $return_val;
|
||||
private mixed $return_val;
|
||||
|
||||
/**
|
||||
* 注解调用器构造函数
|
||||
@ -50,10 +47,10 @@ class AnnotationHandler
|
||||
/**
|
||||
* 立刻中断注解调用器执行
|
||||
*
|
||||
* @param mixed $return_var 中断执行返回值,传入null则代表无返回值
|
||||
* @param null|mixed $return_var 中断执行返回值,传入null则代表无返回值
|
||||
* @throws InterruptException
|
||||
*/
|
||||
public static function interrupt($return_var = null)
|
||||
public static function interrupt(mixed $return_var = null)
|
||||
{
|
||||
throw new InterruptException($return_var);
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ class AnnotationMap
|
||||
* @var array<string, array<AnnotationBase>>
|
||||
* @internal
|
||||
*/
|
||||
public static $_list = [];
|
||||
public static array $_list = [];
|
||||
|
||||
/**
|
||||
* 存取注解对象的三维列表,key1是注解所在的类名,key2是注解所在的方法名,value是该方法标注的注解们(数组)
|
||||
@ -23,14 +23,14 @@ class AnnotationMap
|
||||
* @var array<string, array<string, array<AnnotationBase>>>
|
||||
* @internal
|
||||
*/
|
||||
public static $_map = [];
|
||||
public static array $_map = [];
|
||||
|
||||
/**
|
||||
* 将Parser解析后的注解注册到全局的 AnnotationMap
|
||||
*
|
||||
* @param AnnotationParser $parser 注解解析器
|
||||
*/
|
||||
public static function loadAnnotationByParser(AnnotationParser $parser)
|
||||
public static function loadAnnotationByParser(AnnotationParser $parser): void
|
||||
{
|
||||
// 生成后加入到全局list中
|
||||
self::$_list = array_merge(self::$_list, $parser->generateAnnotationList());
|
||||
|
||||
@ -7,13 +7,11 @@ namespace ZM\Annotation;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Koriym\Attributes\AttributeReader;
|
||||
use Koriym\Attributes\DualReader;
|
||||
use ReflectionMethod;
|
||||
use ZM\Annotation\Http\Controller;
|
||||
use ZM\Annotation\Http\Route;
|
||||
use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
use ZM\Annotation\Interfaces\Level;
|
||||
use ZM\Annotation\Middleware\Middleware;
|
||||
use ZM\Exception\ConfigException;
|
||||
use ZM\Store\FileSystem;
|
||||
use ZM\Utils\HttpUtil;
|
||||
|
||||
@ -25,27 +23,27 @@ class AnnotationParser
|
||||
/**
|
||||
* @var array 要解析的路径列表
|
||||
*/
|
||||
private $path_list = [];
|
||||
private array $path_list = [];
|
||||
|
||||
/**
|
||||
* @var float 用于计算解析时间用的
|
||||
*/
|
||||
private $start_time;
|
||||
private float $start_time;
|
||||
|
||||
/**
|
||||
* @var array 用于解析的注解解析树,格式见下方的注释
|
||||
*/
|
||||
private $annotation_tree = [];
|
||||
private array $annotation_tree = [];
|
||||
|
||||
/**
|
||||
* @var array 用于生成"类-方法"对应"注解列表"的数组
|
||||
*/
|
||||
private $annotation_map = [];
|
||||
private array $annotation_map = [];
|
||||
|
||||
/**
|
||||
* @var array 特殊的注解解析器回调列表
|
||||
*/
|
||||
private $special_parsers = [];
|
||||
private array $special_parsers = [];
|
||||
|
||||
/**
|
||||
* AnnotationParser constructor.
|
||||
@ -54,6 +52,7 @@ class AnnotationParser
|
||||
{
|
||||
$this->start_time = microtime(true);
|
||||
|
||||
// 如果需要,添加内置的注解解析器
|
||||
if ($with_internal_parsers) {
|
||||
$this->special_parsers = [
|
||||
Middleware::class => [function (Middleware $middleware) { \middleware()->bindMiddleware([resolve($middleware->class), $middleware->method], $middleware->name, $middleware->params); }],
|
||||
@ -73,103 +72,127 @@ class AnnotationParser
|
||||
$this->special_parsers[$class_name][] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册各个模块类的注解和模块level的排序
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function parseAll()
|
||||
public function parse(array $path): void
|
||||
{
|
||||
// 对每个设置的路径依次解析
|
||||
foreach ($this->path_list as $path) {
|
||||
logger()->debug('parsing annotation in ' . $path[0] . ':' . $path[1]);
|
||||
// 写日志
|
||||
logger()->debug('parsing annotation in ' . $path[0] . ':' . $path[1]);
|
||||
|
||||
// 首先获取路径下所有的类(通过 PSR-4 标准解析)
|
||||
$all_class = FileSystem::getClassesPsr4($path[0], $path[1]);
|
||||
// 首先获取路径下所有的类(通过 PSR-4 标准解析)
|
||||
$all_class = FileSystem::getClassesPsr4($path[0], $path[1]);
|
||||
|
||||
// 读取配置文件中配置的忽略解析的注解名,防止误解析一些别的地方需要的注解,比如@mixin
|
||||
$conf = config('global.runtime.annotation_reader_ignore');
|
||||
// 有两种方式,第一种是通过名称,第二种是通过命名空间
|
||||
if (isset($conf['name']) && is_array($conf['name'])) {
|
||||
foreach ($conf['name'] as $v) {
|
||||
AnnotationReader::addGlobalIgnoredName($v);
|
||||
}
|
||||
// 读取配置文件中配置的忽略解析的注解名,防止误解析一些别的地方需要的注解,比如@mixin
|
||||
$conf = config('global.runtime.annotation_reader_ignore');
|
||||
// 有两种方式,第一种是通过名称,第二种是通过命名空间
|
||||
if (isset($conf['name']) && is_array($conf['name'])) {
|
||||
foreach ($conf['name'] as $v) {
|
||||
AnnotationReader::addGlobalIgnoredName($v);
|
||||
}
|
||||
if (isset($conf['namespace']) && is_array($conf['namespace'])) {
|
||||
foreach ($conf['namespace'] as $v) {
|
||||
AnnotationReader::addGlobalIgnoredNamespace($v);
|
||||
}
|
||||
}
|
||||
if (isset($conf['namespace']) && is_array($conf['namespace'])) {
|
||||
foreach ($conf['namespace'] as $v) {
|
||||
AnnotationReader::addGlobalIgnoredNamespace($v);
|
||||
}
|
||||
// 因为mixin常用,且框架默认不需要解析,则全局忽略
|
||||
AnnotationReader::addGlobalIgnoredName('mixin');
|
||||
}
|
||||
// 因为mixin常用,且框架默认不需要解析,则全局忽略
|
||||
AnnotationReader::addGlobalIgnoredName('mixin');
|
||||
|
||||
// 声明一个既可以解析注解又可以解析Attribute的双reader来读取注解和Attribute
|
||||
$reader = new DualReader(new AnnotationReader(), new AttributeReader());
|
||||
foreach ($all_class as $v) {
|
||||
logger()->debug('正在检索 ' . $v);
|
||||
// 声明一个既可以解析注解又可以解析Attribute的双reader来读取注解和Attribute
|
||||
$reader = new DualReader(new AnnotationReader(), new AttributeReader());
|
||||
foreach ($all_class as $v) {
|
||||
logger()->debug('正在检索 ' . $v);
|
||||
|
||||
// 通过反射实现注解读取
|
||||
$reflection_class = new \ReflectionClass($v);
|
||||
$methods = $reflection_class->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
$class_annotations = $reader->getClassAnnotations($reflection_class);
|
||||
// 这段为新加的:start
|
||||
// 这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
|
||||
/*
|
||||
$annotation_map: {
|
||||
Module\Example\Hello: {
|
||||
class_annotations: [
|
||||
注解对象1, 注解对象2, ...
|
||||
],
|
||||
methods: [
|
||||
ReflectionMethod, ReflectionMethod, ...
|
||||
],
|
||||
methods_annotations: {
|
||||
foo: [ 注解对象1, 注解对象2, ... ],
|
||||
bar: [ 注解对象1, 注解对象2, ... ],
|
||||
}
|
||||
// 通过反射实现注解读取
|
||||
$reflection_class = new \ReflectionClass($v);
|
||||
$methods = $reflection_class->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
$class_annotations = $reader->getClassAnnotations($reflection_class);
|
||||
// 这段为新加的:start
|
||||
// 这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
|
||||
/*
|
||||
$annotation_map: {
|
||||
Module\Example\Hello: {
|
||||
class_annotations: [
|
||||
注解对象1, 注解对象2, ...
|
||||
],
|
||||
methods: [
|
||||
ReflectionMethod, ReflectionMethod, ...
|
||||
],
|
||||
methods_annotations: {
|
||||
foo: [ 注解对象1, 注解对象2, ... ],
|
||||
bar: [ 注解对象1, 注解对象2, ... ],
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
|
||||
// 保存对class的注解
|
||||
$this->annotation_tree[$v]['class_annotations'] = $class_annotations;
|
||||
// 保存类成员的方法的对应反射对象们
|
||||
$this->annotation_tree[$v]['methods'] = $methods;
|
||||
// 保存对每个方法获取到的注解们
|
||||
foreach ($methods as $method) {
|
||||
$this->annotation_tree[$v]['methods_annotations'][$method->getName()] = $reader->getMethodAnnotations($method);
|
||||
// 保存对class的注解
|
||||
$this->annotation_tree[$v]['class_annotations'] = $class_annotations;
|
||||
// 保存类成员的方法的对应反射对象们
|
||||
$this->annotation_tree[$v]['methods'] = $methods;
|
||||
// 保存对每个方法获取到的注解们
|
||||
foreach ($methods as $method) {
|
||||
$this->annotation_tree[$v]['methods_annotations'][$method->getName()] = $reader->getMethodAnnotations($method);
|
||||
}
|
||||
|
||||
// 因为适用于类的注解有一些比较特殊,比如有向下注入的,有控制行为的,所以需要遍历一下下放到方法里
|
||||
foreach ($this->annotation_tree[$v]['class_annotations'] as $vs) {
|
||||
$vs->class = $v;
|
||||
|
||||
// 预处理0:排除所有非继承于 AnnotationBase 的注解
|
||||
if (!$vs instanceof AnnotationBase) {
|
||||
logger()->notice(get_class($vs) . ' is not extended from ' . AnnotationBase::class);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 因为适用于类的注解有一些比较特殊,比如有向下注入的,有控制行为的,所以需要遍历一下下放到方法里
|
||||
foreach ($this->annotation_tree[$v]['class_annotations'] as $vs) {
|
||||
$vs->class = $v;
|
||||
// 预处理1:如果类包含了@Closed注解,则跳过这个类
|
||||
if ($vs instanceof Closed) {
|
||||
unset($this->annotation_tree[$v]);
|
||||
continue 2;
|
||||
}
|
||||
|
||||
// 预处理0:排除所有非继承于 AnnotationBase 的注解
|
||||
if (!$vs instanceof AnnotationBase) {
|
||||
logger()->notice(get_class($vs) . ' is not extended from ' . AnnotationBase::class);
|
||||
// 预处理2:将适用于每一个函数的注解到类注解重新注解到每个函数下面
|
||||
if ($vs instanceof ErgodicAnnotation) {
|
||||
foreach (($this->annotation_tree[$v]['methods'] ?? []) as $method) {
|
||||
// 用 clone 的目的是生成个独立的对象,避免和 class 以及方法之间互相冲突
|
||||
$copy = clone $vs;
|
||||
$copy->method = $method->getName();
|
||||
$this->annotation_tree[$v]['methods_annotations'][$method->getName()][] = $copy;
|
||||
}
|
||||
}
|
||||
|
||||
// 预处理3:调用自定义解析器
|
||||
foreach (($this->special_parsers[get_class($vs)] ?? []) as $parser) {
|
||||
$result = $parser($vs);
|
||||
if ($result === true) {
|
||||
continue 2;
|
||||
}
|
||||
if ($result === false) {
|
||||
continue 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 预处理3:处理每个函数上面的特殊注解,就是需要操作一些东西的
|
||||
foreach (($this->annotation_tree[$v]['methods_annotations'] ?? []) as $method_name => $methods_annotations) {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 预处理1:如果类包含了@Closed注解,则跳过这个类
|
||||
if ($vs instanceof Closed) {
|
||||
unset($this->annotation_tree[$v]);
|
||||
// 预处理3.1:给所有注解对象绑定当前的类名和方法名
|
||||
$method_anno->class = $v;
|
||||
$method_anno->method = $method_name;
|
||||
|
||||
// 预处理3.2:如果包含了@Closed注解,则跳过这个方法的注解解析
|
||||
if ($method_anno instanceof Closed) {
|
||||
unset($this->annotation_tree[$v]['methods_annotations'][$method_name]);
|
||||
continue 2;
|
||||
}
|
||||
|
||||
// 预处理2:将适用于每一个函数的注解到类注解重新注解到每个函数下面
|
||||
if ($vs instanceof ErgodicAnnotation) {
|
||||
foreach (($this->annotation_tree[$v]['methods'] ?? []) as $method) {
|
||||
// 用 clone 的目的是生成个独立的对象,避免和 class 以及方法之间互相冲突
|
||||
$copy = clone $vs;
|
||||
$copy->method = $method->getName();
|
||||
$this->annotation_tree[$v]['methods_annotations'][$method->getName()][] = $copy;
|
||||
}
|
||||
}
|
||||
|
||||
// 预处理3:调用自定义解析器
|
||||
foreach (($this->special_parsers[get_class($vs)] ?? []) as $parser) {
|
||||
$result = $parser($vs);
|
||||
// 预处理3.3:调用自定义解析器
|
||||
foreach (($this->special_parsers[get_class($method_anno)] ?? []) as $parser) {
|
||||
$result = $parser($method_anno);
|
||||
if ($result === true) {
|
||||
continue 2;
|
||||
}
|
||||
@ -177,44 +200,23 @@ class AnnotationParser
|
||||
continue 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 预处理3:处理每个函数上面的特殊注解,就是需要操作一些东西的
|
||||
foreach (($this->annotation_tree[$v]['methods_annotations'] ?? []) as $method_name => $methods_annotations) {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 预处理3.1:给所有注解对象绑定当前的类名和方法名
|
||||
$method_anno->class = $v;
|
||||
$method_anno->method = $method_name;
|
||||
|
||||
// 预处理3.2:如果包含了@Closed注解,则跳过这个方法的注解解析
|
||||
if ($method_anno instanceof Closed) {
|
||||
unset($this->annotation_tree[$v]['methods_annotations'][$method_name]);
|
||||
continue 2;
|
||||
}
|
||||
|
||||
// 预处理3.3:调用自定义解析器
|
||||
foreach (($this->special_parsers[get_class($method_anno)] ?? []) as $parser) {
|
||||
$result = $parser($method_anno);
|
||||
if ($result === true) {
|
||||
continue 2;
|
||||
}
|
||||
if ($result === false) {
|
||||
continue 3;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果上方没有解析或返回了 true,则添加到注解解析列表中
|
||||
$this->annotation_map[$v][$method_name][] = $method_anno;
|
||||
}
|
||||
// 如果上方没有解析或返回了 true,则添加到注解解析列表中
|
||||
$this->annotation_map[$v][$method_name][] = $method_anno;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册各个模块类的注解和模块level的排序
|
||||
*/
|
||||
public function parseAll(): void
|
||||
{
|
||||
// 对每个设置的路径依次解析
|
||||
foreach ($this->path_list as $path) {
|
||||
$this->parse($path);
|
||||
}
|
||||
logger()->debug('解析注解完毕!');
|
||||
}
|
||||
|
||||
@ -295,7 +297,7 @@ class AnnotationParser
|
||||
/**
|
||||
* 添加注解路由
|
||||
*/
|
||||
private function addRouteAnnotation(Route $vss)
|
||||
private function addRouteAnnotation(Route $vss): void
|
||||
{
|
||||
// 拿到所属方法的类上面有没有控制器的注解
|
||||
$prefix = '';
|
||||
|
||||
@ -24,13 +24,11 @@ use ZM\Annotation\Interfaces\Level;
|
||||
class BindEvent extends AnnotationBase implements Level
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @Required()
|
||||
*/
|
||||
public $event_class;
|
||||
public string $event_class;
|
||||
|
||||
/** @var int */
|
||||
public $level = 800;
|
||||
public int $level = 800;
|
||||
|
||||
/**
|
||||
* @param string $event_class 绑定事件的类型
|
||||
|
||||
@ -19,8 +19,7 @@ use ZM\Annotation\AnnotationBase;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||
class Init extends AnnotationBase
|
||||
{
|
||||
/** @var int */
|
||||
public $worker = 0;
|
||||
public int $worker = 0;
|
||||
|
||||
public function __construct(int $worker = 0)
|
||||
{
|
||||
|
||||
@ -21,10 +21,9 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
class Controller extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @Required()
|
||||
*/
|
||||
public $prefix = '';
|
||||
public string $prefix = '';
|
||||
|
||||
public function __construct(string $prefix)
|
||||
{
|
||||
|
||||
@ -20,26 +20,18 @@ use ZM\Annotation\AnnotationBase;
|
||||
class Route extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @Required()
|
||||
*/
|
||||
public $route = '';
|
||||
public string $route = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
public string $name = '';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $request_method = ['GET', 'POST'];
|
||||
public array $request_method = ['GET', 'POST'];
|
||||
|
||||
/**
|
||||
* Routing path params binding. eg. {"id"="\d+"}
|
||||
* @var array
|
||||
*/
|
||||
public $params = [];
|
||||
public array $params = [];
|
||||
|
||||
public function __construct($route, $name = '', $request_method = ['GET', 'POST'], $params = [])
|
||||
{
|
||||
@ -49,7 +41,7 @@ class Route extends AnnotationBase
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
public static function make($route, $name = '', $request_method = ['GET', 'POST'], $params = [])
|
||||
public static function make($route, $name = '', $request_method = ['GET', 'POST'], $params = []): static
|
||||
{
|
||||
return new static($route, $name, $request_method, $params);
|
||||
}
|
||||
|
||||
@ -21,15 +21,14 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
class Middleware extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @Required()
|
||||
*/
|
||||
public $name;
|
||||
public string $name;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public $params = [];
|
||||
public array $params = [];
|
||||
|
||||
public function __construct($name, $params = [])
|
||||
{
|
||||
|
||||
@ -23,41 +23,30 @@ use ZM\Exception\ZMKnownException;
|
||||
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
|
||||
class BotCommand extends AnnotationBase implements Level
|
||||
{
|
||||
/** @var string */
|
||||
public $name = '';
|
||||
public string $name = '';
|
||||
|
||||
/** @var string */
|
||||
public $match = '';
|
||||
public string $match = '';
|
||||
|
||||
/** @var string */
|
||||
public $pattern = '';
|
||||
public string $pattern = '';
|
||||
|
||||
/** @var string */
|
||||
public $regex = '';
|
||||
public string $regex = '';
|
||||
|
||||
/** @var string */
|
||||
public $start_with = '';
|
||||
public string $start_with = '';
|
||||
|
||||
/** @var string */
|
||||
public $end_with = '';
|
||||
public string $end_with = '';
|
||||
|
||||
/** @var string */
|
||||
public $keyword = '';
|
||||
public string $keyword = '';
|
||||
|
||||
/** @var string[] */
|
||||
public $alias = [];
|
||||
public array $alias = [];
|
||||
|
||||
/** @var string */
|
||||
public $message_type = '';
|
||||
public string $message_type = '';
|
||||
|
||||
/** @var string */
|
||||
public $user_id = '';
|
||||
public string $user_id = '';
|
||||
|
||||
/** @var string */
|
||||
public $group_id = '';
|
||||
public string $group_id = '';
|
||||
|
||||
/** @var int */
|
||||
public $level = 20;
|
||||
public int $level = 20;
|
||||
|
||||
private array $arguments = [];
|
||||
|
||||
|
||||
@ -39,6 +39,7 @@ class HttpEventListener
|
||||
$handler->handleAll($event);
|
||||
// dump($event->getResponse());
|
||||
$node = null;
|
||||
/** @var null|array $params */
|
||||
$params = null;
|
||||
// 如果状态是 Normal,那么说明跑了一遍没有阻塞或者其他的情况,我就直接跑一遍内部的路由分发和静态文件分发
|
||||
if ($handler->getStatus() === AnnotationHandler::STATUS_NORMAL && $event->getResponse() === null) {
|
||||
|
||||
@ -31,6 +31,7 @@ use ZM\Exception\SingletonViolationException;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Logger\TablePrinter;
|
||||
use ZM\Process\ProcessStateManager;
|
||||
use ZM\Utils\EasterEgg;
|
||||
|
||||
/**
|
||||
* 框架入口类
|
||||
@ -55,14 +56,14 @@ class Framework
|
||||
/** @var array<array<string, string>> 启动注解列表 */
|
||||
protected array $setup_annotations = [];
|
||||
|
||||
/** @var array|string[] 框架启动前置的内容,由上到下执行 */
|
||||
protected array $bootstrappers = [
|
||||
// 驱动前置
|
||||
Bootstrap\LoadConfiguration::class,
|
||||
Bootstrap\LoadGlobalDefines::class,
|
||||
Bootstrap\RegisterLogger::class,
|
||||
Bootstrap\HandleExceptions::class,
|
||||
Bootstrap\RegisterEventProvider::class,
|
||||
Bootstrap\SetInternalTimezone::class,
|
||||
Bootstrap\LoadConfiguration::class, // 加载配置文件
|
||||
Bootstrap\LoadGlobalDefines::class, // 加载框架级别的全局常量声明
|
||||
Bootstrap\RegisterLogger::class, // 加载 Logger
|
||||
Bootstrap\HandleExceptions::class, // 注册异常处理器
|
||||
Bootstrap\RegisterEventProvider::class, // 绑定框架的 EventProvider 到 libob 的 Driver 上
|
||||
Bootstrap\SetInternalTimezone::class, // 设置时区
|
||||
];
|
||||
|
||||
/**
|
||||
@ -84,6 +85,8 @@ class Framework
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化框架
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function init(): Framework
|
||||
@ -121,9 +124,10 @@ class Framework
|
||||
* 停止框架运行
|
||||
*
|
||||
* 未测试
|
||||
* @param int $retcode 退出码
|
||||
* @throws ZMKnownException
|
||||
*/
|
||||
public function stop(int $retcode = 0)
|
||||
public function stop(int $retcode = 0): void
|
||||
{
|
||||
switch ($this->driver->getName()) {
|
||||
case 'swoole':
|
||||
@ -368,14 +372,8 @@ class Framework
|
||||
{
|
||||
// 先获取终端宽度,防止超过边界换行
|
||||
$tty_width = (new TablePrinter([]))->fetchTerminalSize();
|
||||
// caidan
|
||||
$str = substr(sprintf('%o', fileperms(__FILE__)), -4);
|
||||
if ($str == '0777') {
|
||||
$table = ['@' => '9fX1', '!' => 'ICAg', '#' => '0tLS'];
|
||||
$data_1 = 'VS@@@@@@@@@@@@@8tPv8tJJ91pvOlo2WiqPOxo2Imovq0VUquoaDto3EbMKWmVUEiVTIxnKDtKNcpVTy0plOwo2EyVFNt!!!!!!!!!VP8XVP#############0tPvNt';
|
||||
$data_2 = $data_1 . '!!KPNtVS5sK14X!!!KPNtXT9iXIksK1@9sPvNt!!!VPusKlyp!!VPypY1jX!!!!!VUk8YF0gYKptsNbt!!!!!sUjt!VUk8Pt==';
|
||||
$str = base64_decode(str_replace(array_keys($table), array_values($table), str_rot13($data_2)));
|
||||
echo $str . PHP_EOL;
|
||||
if ($s = EasterEgg::checkFrameworkPermissionCall()) {
|
||||
echo $s;
|
||||
return;
|
||||
}
|
||||
// 从源码目录、框架本身的初始目录寻找 MOTD 文件
|
||||
|
||||
@ -11,11 +11,9 @@ use ZM\Exception\InvalidArgumentException;
|
||||
*/
|
||||
class Pipeline
|
||||
{
|
||||
/** @var mixed */
|
||||
private $value;
|
||||
private mixed $value;
|
||||
|
||||
/** @var array */
|
||||
private $middlewares;
|
||||
private array $middlewares;
|
||||
|
||||
/**
|
||||
* 向管道发送数据
|
||||
@ -23,7 +21,7 @@ class Pipeline
|
||||
* @param mixed $value 数据
|
||||
* @return $this
|
||||
*/
|
||||
public function send($value): Pipeline
|
||||
public function send(mixed $value): Pipeline
|
||||
{
|
||||
$this->value = $value;
|
||||
return $this;
|
||||
|
||||
@ -8,22 +8,25 @@ use ZM\Annotation\Http\Route;
|
||||
use ZM\Annotation\OneBot\BotCommand;
|
||||
use ZM\Annotation\OneBot\BotEvent;
|
||||
|
||||
class InstantPlugin
|
||||
/**
|
||||
* 单文件插件声明类
|
||||
*/
|
||||
class ZMPlugin
|
||||
{
|
||||
/** @var string 插件目录 */
|
||||
protected $dir;
|
||||
protected string $dir;
|
||||
|
||||
/** @var array 机器人事件列表 */
|
||||
protected $bot_events = [];
|
||||
protected array $bot_events = [];
|
||||
|
||||
/** @var array 机器人指令列表 */
|
||||
protected $bot_commands = [];
|
||||
protected array $bot_commands = [];
|
||||
|
||||
/** @var array 全局的事件列表 */
|
||||
protected $events = [];
|
||||
protected array $events = [];
|
||||
|
||||
/** @var array 注册的路由列表 */
|
||||
protected $routes = [];
|
||||
protected array $routes = [];
|
||||
|
||||
public function __construct(string $dir)
|
||||
{
|
||||
@ -45,7 +48,7 @@ class InstantPlugin
|
||||
$this->bot_commands[] = $command;
|
||||
}
|
||||
|
||||
public function registerEvent(string $event_name, callable $callback, int $level = 20)
|
||||
public function addEvent(string $event_name, callable $callback, int $level = 20)
|
||||
{
|
||||
$this->events[] = [$event_name, $callback, $level];
|
||||
}
|
||||
25
src/ZM/Utils/EasterEgg.php
Normal file
25
src/ZM/Utils/EasterEgg.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
class EasterEgg
|
||||
{
|
||||
/**
|
||||
* 第一个彩蛋:把炸毛的源码修改为 777 权限是不安全的,会蹦出牛告诉你哦
|
||||
*/
|
||||
public static function checkFrameworkPermissionCall(): ?string
|
||||
{
|
||||
// caidan
|
||||
$str = substr(sprintf('%o', fileperms(__FILE__)), -4);
|
||||
if ($str == '0777') {
|
||||
$table = ['@' => '9fX1', '!' => 'ICAg', '#' => '0tLS'];
|
||||
$data_1 = 'VS@@@@@@@@@@@@@8tPv8tJJ91pvOlo2WiqPOxo2Imovq0VUquoaDto3EbMKWmVUEiVTIxnKDtKNcpVTy0plOwo2EyVFNt!!!!!!!!!VP8XVP#############0tPvNt';
|
||||
$data_2 = $data_1 . '!!KPNtVS5sK14X!!!KPNtXT9iXIksK1@9sPvNt!!!VPusKlyp!!VPypY1jX!!!!!VUk8YF0gYKptsNbt!!!!!sUjt!VUk8Pt==';
|
||||
$str = base64_decode(str_replace(array_keys($table), array_values($table), str_rot13($data_2)));
|
||||
return $str . PHP_EOL;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,12 @@ namespace ZM;
|
||||
|
||||
use ZM\Command\Server\ServerStartCommand;
|
||||
use ZM\Exception\SingletonViolationException;
|
||||
use ZM\Plugin\InstantPlugin;
|
||||
use ZM\Plugin\ZMPlugin;
|
||||
|
||||
class InstantApplication extends InstantPlugin
|
||||
class ZMApplication extends ZMPlugin
|
||||
{
|
||||
/** @var null|InstantApplication 存储单例类的变量 */
|
||||
private static ?InstantApplication $obj;
|
||||
/** @var null|ZMApplication 存储单例类的变量 */
|
||||
private static ?ZMApplication $obj;
|
||||
|
||||
/** @var array 存储要传入的args */
|
||||
private array $args = [];
|
||||
@ -26,13 +26,13 @@ class InstantApplication extends InstantPlugin
|
||||
$this->args = ServerStartCommand::exportOptionArray();
|
||||
}
|
||||
|
||||
public function withConfig(array $config): InstantApplication
|
||||
public function withConfig(array $config): ZMApplication
|
||||
{
|
||||
// TODO: 完成patch config
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withArgs(array $args): InstantApplication
|
||||
public function withArgs(array $args): ZMApplication
|
||||
{
|
||||
$this->args = array_replace_recursive($this->args, $args);
|
||||
return $this;
|
||||
Loading…
x
Reference in New Issue
Block a user