Merge pull request #181 from zhamao-robot/8.0-upgrade

兼容 8.x PHP 一些改动
This commit is contained in:
Jerry 2022-12-18 00:41:56 +08:00 committed by GitHub
commit 14840715bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 218 additions and 313 deletions

View File

@ -1,17 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Reload Zhamao Server" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="./zhamao server:reload &amp;&amp; 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>

View File

@ -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>

View File

@ -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>

View File

@ -1,17 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Stop Zhamao Server" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="./zhamao server:stop &amp;&amp; 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>

View File

@ -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",

View File

@ -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;
},
];

View File

@ -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

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
$plugin = new InstantPlugin(__DIR__);
$plugin = new ZMPlugin(__DIR__);
/*
* 发送 "测试 123",回复 "你好123"

View File

@ -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));
});

View File

@ -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');

View File

@ -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);
}

View File

@ -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());

View File

@ -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 = '';

View File

@ -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 绑定事件的类型

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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 = [])
{

View File

@ -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 = [];

View File

@ -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) {

View File

@ -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 文件

View File

@ -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;

View File

@ -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];
}

View 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;
}
}

View File

@ -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;