mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-04 07:15:36 +08:00
Compare commits
41 Commits
2.7.0-beta
...
2.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5a6f1fea4 | ||
|
|
ba2777137b | ||
|
|
6d90be164a | ||
|
|
4da6f5859a | ||
|
|
15d4ea710a | ||
|
|
f0541c1f32 | ||
|
|
2b8cab1824 | ||
|
|
61c7972915 | ||
|
|
44a0eec74c | ||
|
|
e57753e44b | ||
|
|
74e91a2950 | ||
|
|
7ce3ef41df | ||
|
|
444a77933a | ||
|
|
78f78c607d | ||
|
|
69155002dc | ||
|
|
475d14fab7 | ||
|
|
f4d7e63358 | ||
|
|
f222d2b45b | ||
|
|
d0155fe1da | ||
|
|
4737d0b507 | ||
|
|
09bd0197bb | ||
|
|
f0f120bd32 | ||
|
|
c897da29c6 | ||
|
|
e347e254e8 | ||
|
|
12363aebf0 | ||
|
|
ff0b925313 | ||
|
|
a6b4bd9b80 | ||
|
|
485fa5476c | ||
|
|
689076d97c | ||
|
|
cca6102e91 | ||
|
|
095855162b | ||
|
|
326f934013 | ||
|
|
35b0c258fe | ||
|
|
6650846b15 | ||
|
|
a33d320f4c | ||
|
|
0bcfea6aa4 | ||
|
|
db6e63e91c | ||
|
|
a7f84fb53a | ||
|
|
ce7f2b1765 | ||
|
|
abbfb59eff | ||
|
|
b57fef16f9 |
59
.github/workflows/integration-test.yml
vendored
Normal file
59
.github/workflows/integration-test.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Integration Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
- ready_for_review
|
||||
- review_requested
|
||||
|
||||
jobs:
|
||||
integration:
|
||||
name: Integration Test (PHP ${{ matrix.php-versions }}) (OS ${{ matrix.operating-system }})
|
||||
runs-on: ${{ matrix.operating-system }}
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system: [ "ubuntu-latest", "macos-latest" ]
|
||||
php-versions: [ "7.2", "7.3", "7.4", "8.0", "8.1" ]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: "shivammathur/setup-php@v2"
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: swoole, posix, json
|
||||
|
||||
- name: Setup problem matchers for PHP
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
|
||||
- name: Validate composer.json
|
||||
run: "composer validate --strict"
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install Composer Dependencies
|
||||
run: "composer install --prefer-dist --no-progress --optimize-autoloader"
|
||||
|
||||
- name: Run Static Analysis
|
||||
run: "composer analyse"
|
||||
|
||||
- name: Run PHP CS Fixer Check
|
||||
run: "./vendor/bin/php-cs-fixer fix --dry-run --diff"
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Docs Build
|
||||
name: MkDocs Auto Deploy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,6 +13,7 @@ composer.lock
|
||||
/runtime/
|
||||
/tmp/
|
||||
/temp/
|
||||
/site/
|
||||
|
||||
# go-cqhttp快速安装启动相关(可能被废弃)
|
||||
/ext/go-cqhttp/data/
|
||||
|
||||
@@ -65,7 +65,6 @@ return (new PhpCsFixer\Config())
|
||||
'standardize_not_equals' => true,
|
||||
'multiline_comment_opening_closing' => true,
|
||||
'phpdoc_summary' => false,
|
||||
'class_reference_name_casing' => false,
|
||||
])
|
||||
->setFinder(
|
||||
PhpCsFixer\Finder::create()
|
||||
|
||||
15
README.md
15
README.md
@@ -7,7 +7,7 @@
|
||||
[](https://github.com/zhamao-robot/zhamao-framework/blob/master/LICENSE)
|
||||
[](https://packagist.org/packages/zhamao/framework)
|
||||
[](https://github.com/howmanybots/onebot)
|
||||

|
||||

|
||||
|
||||
[](https://github.com/zhamao-robot/zhamao-framework/search?q=AnnotationBase)
|
||||
[](https://github.com/zhamao-robot/zhamao-framework/search?q=TODO)
|
||||
@@ -62,20 +62,15 @@ vendor/bin/start server
|
||||
## 特点
|
||||
- 原生为多账号设计,支持多个机器人负载均衡
|
||||
- 使用 Swoole 多工作进程机制和协程加持,尽可能简单的情况下提升了性能
|
||||
- 灵活的注解事件绑定机制
|
||||
- 灵活的注解事件绑定机制,可兼容使用 PHP8 的 Attribute(>=2.7 可用)
|
||||
- 易用的上下文,模块内随处可用
|
||||
- 采用模块化编写,可自由搭配其他 composer 组件
|
||||
- 采用模块化编写,可自由搭配其他 composer 组件,也可单文件面向过程编写
|
||||
- 常驻内存,全局缓存变量随处使用,提供多种缓存方案
|
||||
- 自带 MySQL、Redis 等数据库连接池等数据库连接方案
|
||||
- 本身为 HTTP 服务器、WebSocket 服务器,可以构建属于自己的 HTTP API 接口
|
||||
- 静态文件服务器,可将前端合并到一起
|
||||
- 自带 PHP + Swoole 环境,无需手动编译安装,by [crazywhalecc/static-php-cli](https://github.com/crazywhalecc/static-php-cli)
|
||||
|
||||
## 从 v1 升级
|
||||
炸毛框架 v2 相对 v1 版本改动了不少内容,其中包括框架底层机制、注解事件分发、调试、命名空间等变化,详情可查看上方文档。
|
||||
|
||||
如果旧版框架使用过程中无问题且对新功能暂无需求,可以继续使用 v1 版本,后续也将维护安全类更新和修复致命 bug。
|
||||
|
||||
## 下载源码
|
||||
框架源码可直接克隆本仓库进行编辑,如果你在国内,访问 GitHub 和 clone 仓库比较慢,可以将 `github.com` 替换为 `fgit.zhamao.me` 进行加速。
|
||||
|
||||
@@ -93,12 +88,10 @@ vendor/bin/start server
|
||||
### 支付宝
|
||||

|
||||
|
||||
如果你对我们的周边感兴趣,我们还有炸毛机器人定制 logo 的雨伞,详情咨询作者 QQ,我们会作为您捐助了本项目!
|
||||
|
||||
## 关于
|
||||
框架和 SDK 是 炸毛机器人 项目的核心框架开源部分。炸毛机器人是作者写的一个高性能机器人,曾获全国计算机设计大赛一等奖。
|
||||
|
||||
作者的炸毛机器人已从2018年初起稳定运行了**四年**,并且持续迭代。
|
||||
作者的炸毛机器人已从2018年初起稳定运行了**四年半**,并且持续迭代。
|
||||
|
||||
欢迎随时在 HTTP-API 插件群里提问,当然更好的话可以加作者 QQ([627577391](http://wpa.qq.com/msgrd?v=3&uin=627577391&site=qq&menu=yes))或提交 Issue 进行疑难解答。
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
"minimum-stability": "stable",
|
||||
"license": "Apache-2.0",
|
||||
"extra": {
|
||||
"exclude_annotate": [
|
||||
"src/ZM"
|
||||
],
|
||||
"zm": {
|
||||
"exclude-annotation-path": [
|
||||
"src/ZM"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
"post-merge": "composer install",
|
||||
"pre-commit": [
|
||||
@@ -35,19 +37,19 @@
|
||||
"php": "^7.2 || ^7.3 || ^7.4 || ^8.0 || ^8.1",
|
||||
"ext-json": "*",
|
||||
"ext-posix": "*",
|
||||
"doctrine/annotations": "~1.12 || ~1.4.0",
|
||||
"doctrine/dbal": "^2.13.1",
|
||||
"jelix/version": "^2.0",
|
||||
"koriym/attributes": "^1.0",
|
||||
"psy/psysh": "^0.11.2",
|
||||
"symfony/console": "~5.0 || ~4.0 || ~3.0",
|
||||
"symfony/polyfill-ctype": "^1.19",
|
||||
"symfony/polyfill-mbstring": "^1.19",
|
||||
"symfony/console": "~5.0 || ~4.0 || ~3.0",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/routing": "~5.0 || ~4.0 || ~3.0",
|
||||
"zhamao/console": "^1.0",
|
||||
"zhamao/config": "^1.0",
|
||||
"zhamao/request": "^1.1",
|
||||
"zhamao/connection-manager": "^1.0",
|
||||
"jelix/version": "^2.0",
|
||||
"league/climate": "^3.6",
|
||||
"psy/psysh": "@stable",
|
||||
"doctrine/dbal": "^2.13.1"
|
||||
"zhamao/console": "^1.0",
|
||||
"zhamao/request": "^1.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ctype": "Use C/C++ extension instead of polyfill will be more efficient",
|
||||
@@ -75,11 +77,11 @@
|
||||
"sort-packages": true
|
||||
},
|
||||
"require-dev": {
|
||||
"swoole/ide-helper": "@dev",
|
||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||
"brainmaestro/composer-git-hooks": "^2.8",
|
||||
"friendsofphp/php-cs-fixer": "^3.2 != 3.7.0",
|
||||
"phpstan/phpstan": "^1.1"
|
||||
"phpstan/phpstan": "^1.1",
|
||||
"phpunit/phpunit": "^8.5 || ^9.0",
|
||||
"swoole/ide-helper": "^4.5"
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
@@ -88,4 +90,4 @@
|
||||
"analyse": "phpstan analyse --memory-limit 300M -l 0 ./src",
|
||||
"cs-fix": "php-cs-fixer fix $1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ $config['crash_dir'] = $config['zm_data'] . 'crash/';
|
||||
/* 对应swoole的server->set参数 */
|
||||
$config['swoole'] = [
|
||||
'log_file' => $config['crash_dir'] . 'swoole_error.log',
|
||||
//'worker_num' => swoole_cpu_num(), //如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算,则可把这里改为1使用全局变量
|
||||
'dispatch_mode' => 2, //包分配原则,见 https://wiki.swoole.com/#/server/setting?id=dispatch_mode
|
||||
// 'worker_num' => swoole_cpu_num(), //如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算,则可把这里改为1使用全局变量
|
||||
'dispatch_mode' => 2, // 包分配原则,见 https://wiki.swoole.com/#/server/setting?id=dispatch_mode
|
||||
'max_coroutine' => 300000,
|
||||
'max_wait_time' => 5,
|
||||
//'task_worker_num' => 4,
|
||||
//'task_enable_coroutine' => true
|
||||
// 'task_worker_num' => 4,
|
||||
// 'task_enable_coroutine' => true
|
||||
];
|
||||
|
||||
/* 一些框架与框架运行时设置的调整 */
|
||||
@@ -44,13 +44,19 @@ $config['runtime'] = [
|
||||
'reload_delay_time' => 800,
|
||||
'global_middleware_binding' => [],
|
||||
'save_console_log_file' => false, // 改为目标路径,则将 Console 输出的日志保存到文件
|
||||
'annotation_reader_ignore' => [ // 设置注解解析器忽略的注解名或命名空间,防止解析到不该解析的
|
||||
'name' => [
|
||||
'mixin',
|
||||
],
|
||||
'namespace' => [],
|
||||
],
|
||||
];
|
||||
|
||||
/* 轻量字符串缓存,默认开启 */
|
||||
$config['light_cache'] = [
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'size' => 512, // 最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, // 单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, // Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => $config['zm_data'] . '_cache.json',
|
||||
'auto_save_interval' => 900,
|
||||
];
|
||||
@@ -102,7 +108,7 @@ $config['http_default_code_page'] = [
|
||||
|
||||
/* zhamao-framework在框架启动时初始化的atomic们 */
|
||||
$config['init_atomics'] = [
|
||||
//'custom_atomic_name' => 0, //自定义添加的Atomic
|
||||
// 'custom_atomic_name' => 0, //自定义添加的Atomic
|
||||
];
|
||||
|
||||
/* 终端日志显示等级(0-4) */
|
||||
|
||||
88
docs/advanced/example/integrate-qingyunke-chatbot.md
Normal file
88
docs/advanced/example/integrate-qingyunke-chatbot.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# 接入青云客智能聊天机器人API
|
||||
|
||||
作为一个群聊机器人,懂得聊天会让机器人增色不少,在大数据和 AI 热潮下,不少厂商都研发了自己的智能聊天 API,例如图灵机器人、腾讯智能闲聊等,大厂开发的 API 自然有着他人无可比拟的健壮性和可靠性,但是随之而来不菲的价格显然并不适合大众开发者。这时候一个免费、可用的智能聊天 API 便非常重要了,其中,青云客是少有的完全免费、无需注册的智能聊天 API,提供了包括智能聊天、歌词、天气查询、笑话等多种有用功能,且接入简单,非常适合新手开发者尝试。
|
||||
|
||||
## 结果演示
|
||||

|
||||
|
||||
|
||||
## 阅读接入指南
|
||||
|
||||
不管接入何种服务,阅读接入指南永远都是最优先、最重要的一步,所幸青云客的接入指南十分简单,简单来说归纳为以下:
|
||||
* 请求:GET https://api.qingyunke.com/api.php
|
||||
* 参数:
|
||||
* * `key` 目前固定为 `free`
|
||||
* * `appid` 目前固定为 `0`
|
||||
* * `msg` 关键词,需要经过 `urlencode`
|
||||
* 注意:返回结果中 `{br}` 代表换行
|
||||
|
||||
## 逻辑编写
|
||||
|
||||
阅读过后,我们便可以进行主要的编写工作了。
|
||||
|
||||
首先,为了机器人的性能考虑,也为了避免过分打扰群聊的聊天,我们希望机器人只有在主动触发(@AT 或者 关键词等)时才会进行智能聊天。
|
||||
|
||||
对于关键词匹配,我们可以使用 `@CQCommand`:
|
||||
|
||||
```php
|
||||
/**
|
||||
* 智能聊天
|
||||
*
|
||||
* @CQCommand(start_with="机器人")
|
||||
*/
|
||||
public function chat()
|
||||
{
|
||||
// 替换掉机器人前缀,并获取消息内容
|
||||
$msg = ctx()->getMessage();
|
||||
$msg = str_replace('机器人', '', $msg);
|
||||
if (empty(trim($msg))) {
|
||||
$msg = ctx()->getFullArg('怎么了?');
|
||||
}
|
||||
|
||||
Console::info('正在获取智能聊天回复:' . $msg);
|
||||
// 请求 API 获取回复
|
||||
$raw_data = file_get_contents('https://api.qingyunke.com/api.php?key=free&appid=0&msg=' . urlencode($msg));
|
||||
try {
|
||||
$data = json_decode($raw_data, true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (\Exception $e) {
|
||||
$data = ['content' => '机器人解析异常,请稍后再试'];
|
||||
Console::warning('无法获取智能聊天回复:' . $e->getMessage());
|
||||
}
|
||||
if ($data['result'] !== 0) {
|
||||
$data = ['content' => '机器人服务异常,请稍后再试'];
|
||||
Console::warning('无法获取智能聊天回复:' . $raw_data);
|
||||
}
|
||||
Console::info('获取智能聊天回复完成:' . $data['content']);
|
||||
// 将 {br} 替换为换行
|
||||
$data['content'] = strtr($data['content'], ['{br}' => "\n"]);
|
||||
return $data['content'];
|
||||
}
|
||||
```
|
||||
|
||||
这样我们的命令便只会在用户发送以`机器人`开头的消息时才会触发。
|
||||
|
||||
同时,我们也希望在 @AT 机器人时也进行回复,此时可以使用 `@CQBefore` 方法进行折中:
|
||||
|
||||
```php
|
||||
/**
|
||||
* 将 AT 机器人的消息交由智能聊天处理
|
||||
*
|
||||
* @CQBefore("message")
|
||||
*/
|
||||
public function changeAt(): bool
|
||||
{
|
||||
// 判断此条消息是否 AT 了机器人
|
||||
if (MessageUtil::isAtMe(ctx()->getMessage(), ctx()->getRobotId())) {
|
||||
// 将 AT 本身从消息中去掉
|
||||
$msg = str_replace(CQ::at(ctx()->getRobotId()), '', ctx()->getMessage());
|
||||
ctx()->setMessage('机器人' . trim($msg));
|
||||
// 调用智能聊天
|
||||
ctx()->reply($this->chat());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
112
docs/advanced/example/weather-bot.md
Normal file
112
docs/advanced/example/weather-bot.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# 基于词性分析和魅族天气的天气查询机器人
|
||||
|
||||
本文将基于 [`jieba-php`](https://github.com/fukuball/jieba-php) 中文分词库以及 [魅族天气 API](https://github.com/shichunlei/-Api/blob/master/MeizuWeather.md) 开发一个天气查询机器人。
|
||||
|
||||
## 结果演示
|
||||

|
||||
尾部的随机表情并非本教程的一部分。
|
||||
|
||||
## 逻辑编写
|
||||
|
||||
[`jieba-php`](https://github.com/fukuball/jieba-php) 是目前比较好用的中文分词库,虽然最近的维护并不活跃,但已足够我们的需求:
|
||||
```shell
|
||||
composer require fukuball/jieba-php:dev-master
|
||||
```
|
||||
|
||||
以下代码使用了本文作者自行编写的天气查询库,需要进行引入:
|
||||
```shell
|
||||
composer require sunxyw/weather
|
||||
```
|
||||
您也可以将以下代码自行改写为直接调用魅族天气 API,详情请参阅[魅族天气 API 文档](https://github.com/shichunlei/-Api/blob/master/MeizuWeather.md)。
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Bot\Module\SmartChat;
|
||||
|
||||
use Fukuball\Jieba\Jieba;
|
||||
use Fukuball\Jieba\Posseg;
|
||||
use Sunxyw\Weather\Weather;
|
||||
use ZM\Annotation\CQ\CQCommand;
|
||||
use ZM\Console\Console;
|
||||
|
||||
class WeatherReport
|
||||
{
|
||||
/**
|
||||
* 加载字典
|
||||
*
|
||||
* @OnStart(worker_id=-1)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initDictionary(): void
|
||||
{
|
||||
// 分词以及词性分析需要载入字典到内存
|
||||
ini_set('memory_limit', '600M');
|
||||
Jieba::init(['dict' => 'small']);
|
||||
Posseg::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询天气
|
||||
*
|
||||
* @CQCommand(keyword="天气")
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function cmdQueryWeather(): string
|
||||
{
|
||||
// 分词并进行词性分析
|
||||
$seg_list = Posseg::cut(ctx()->getMessage());
|
||||
$tags = array_column($seg_list, 'tag');
|
||||
// 找出词性为 ns(地名)的单词
|
||||
$location_index = array_search('ns', $tags, true);
|
||||
$location = $seg_list[$location_index]['word'];
|
||||
|
||||
// 此处引入了本文作者自己写的天气库
|
||||
$w = new Weather();
|
||||
try {
|
||||
$report = $w->getWeather($location);
|
||||
} catch (\InvalidArgumentException) {
|
||||
return '城市输入错误';
|
||||
} catch (\JsonException $e) {
|
||||
Console::warning("天气查询失败:{$e->getMessage()}");
|
||||
return '天气查询失败';
|
||||
}
|
||||
|
||||
$template = <<<EOF
|
||||
%s天气:%s
|
||||
温度:%s℃
|
||||
湿度:%s%%
|
||||
风向:%s %s
|
||||
空气质量:%s
|
||||
------------------------------
|
||||
未来三天天气:
|
||||
%s:%s,日间%s℃,夜间%s℃,吹%s %s
|
||||
%s:%s,日间%s℃,夜间%s℃,吹%s %s
|
||||
%s:%s,日间%s℃,夜间%s℃,吹%s %s
|
||||
EOF;
|
||||
$args = [
|
||||
$report->getCity(),
|
||||
$report->getRealtime()['weather'],
|
||||
$report->getRealtime()['temperature'],
|
||||
$report->getRealtime()['humidity'],
|
||||
$report->getRealtime()['wind_direction'],
|
||||
$report->getRealtime()['wind_speed'],
|
||||
$report->getRealtime()['air_quality'],
|
||||
];
|
||||
foreach (array_slice($report->getForecastDaily(), 0, 3) as $forecast) {
|
||||
$args[] = $forecast['date'];
|
||||
$args[] = $forecast['weather'];
|
||||
$args[] = $forecast['temperature']['day'];
|
||||
$args[] = $forecast['temperature']['night'];
|
||||
$args[] = $forecast['wind_direction'];
|
||||
$args[] = $forecast['wind_speed'];
|
||||
}
|
||||
return vsprintf($template, ...$args);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
1
docs/assets/css/library/default.min.css
vendored
Normal file
1
docs/assets/css/library/default.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.hljs,.hljs-subst{color:#444}.hljs-comment{color:#888}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#bc6060}.hljs-literal{color:#78a960}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
|
||||
@@ -56,7 +56,8 @@ src/
|
||||
```json
|
||||
{
|
||||
"name": "my-first-module",
|
||||
"description": "这个是一个示例模块打包教程"
|
||||
"description": "这个是一个示例模块打包教程",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -71,5 +71,8 @@
|
||||
| E00069 | 框架不能启动两个 ConsoleApplication 实例 | 不要重复使用 `new ConsoleApplication()`。 |
|
||||
| E00070 | 框架找不到 `zm_data` 目录 | 检查配置中指定的 `zm_data` 目录是否存在。 |
|
||||
| E00071 | 框架找不到对应类型的 API 调用类 | 检查 `getExtendedAPI($name)` 传入的 `$name` 是否正确 |
|
||||
| E00072 | 上下文无法找到 | 检查上下文环境,如是否处于协程环境中 |
|
||||
| E00073 | 在类中找不到方法 | 检查调用对象是否存在对应的方法(method)或检查是否插入了对应的macro宏方法 |
|
||||
| E00074 | 参数非法 | 检查调用的参数是否正常(此处可能有多处问题,请看具体调用栈炸掉的地方) |
|
||||
| E99999 | 未知错误 | |
|
||||
|
||||
|
||||
@@ -49,20 +49,22 @@ docker run -it --rm -v $(pwd):/app/ -p 20001:20001 zmbot/swoole vendor/bin/start
|
||||
|
||||
```verilog
|
||||
$ vendor/bin/start server
|
||||
host: 0.0.0.0 | port: 20001
|
||||
log_level: 2 | version: 2.0.0
|
||||
config: global.php | worker_num: 4
|
||||
working_dir: /app/zhamao-framework
|
||||
______
|
||||
|__ / |__ __ _ _ __ ___ __ _ ___
|
||||
/ /| '_ \ / _` | '_ ` _ \ / _` |/ _ \
|
||||
/ /_| | | | (_| | | | | | | (_| | (_) |
|
||||
/____|_| |_|\__,_|_| |_| |_|\__,_|\___/
|
||||
=================================================================
|
||||
working_dir: /app/zhamao-framework-starter
|
||||
listen: 0.0.0.0:20001 | worker: 4 (auto)
|
||||
environment: default | log_level: 2
|
||||
version: 2.7.0 | master_pid: 28449
|
||||
=================================================================
|
||||
______
|
||||
|__ / |__ __ _ _ __ ___ __ _ ___
|
||||
/ /| '_ \ / _` | '_ ` _ \ / _` |/ _ \
|
||||
/ /_| | | | (_| | | | | | | (_| | (_) |
|
||||
/____|_| |_|\__,_|_| |_| |_|\__,_|\___/
|
||||
|
||||
[14:27:31] [S] [#3] Worker #3 已启动
|
||||
[14:27:31] [S] [#0] Worker #0 已启动
|
||||
[14:27:31] [S] [#2] Worker #2 已启动
|
||||
[14:27:31] [S] [#1] Worker #1 已启动
|
||||
[03-20 22:30:56] [S] [#1] Worker #1 started
|
||||
[03-20 22:30:56] [S] [#2] Worker #2 started
|
||||
[03-20 22:30:56] [S] [#3] Worker #3 started
|
||||
[03-20 22:30:56] [S] [#0] Worker #0 started
|
||||
```
|
||||
|
||||
单纯运行 炸毛框架 后,如果不部署或安装启动任何机器人客户端的话,仅仅相当于启动了一个 监听 20001 端口的WebSoket + HTTP 服务器。你可以通过浏览器访问:http://127.0.0.1:20001 ,或者你部署到了服务器后需要输入服务器地址。
|
||||
|
||||
44
docs/javascripts/library/highlight.min.js
vendored
Normal file
44
docs/javascripts/library/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -4,6 +4,72 @@
|
||||
|
||||
同时此处将只使用 build 版本号进行区分。
|
||||
|
||||
## build 448 (2022-3-20)
|
||||
|
||||
- 加快 build 命令的执行速度,取消进度条和提升性能
|
||||
|
||||
## build 447 (2022-3-20)
|
||||
|
||||
- 发布 2.7.0 正式版
|
||||
|
||||
## build 446 (2022-3-20)
|
||||
|
||||
- 新增 `./zhamao server` 下的 `--no-state-check` 参数,关闭“启动框架前的运行状态检查”功能
|
||||
|
||||
## build 445 (2022-3-20)
|
||||
|
||||
- 新增配置项 `runtime`.`annotation_reader_ignore`:支持注解解析器忽略注解的自定义
|
||||
|
||||
## build 444 (2022-3-20)
|
||||
|
||||
- 更改 `extra`.`exclude_annotate` 为 `zm`.`exclude-annotation-path` 项
|
||||
|
||||
## build 443 (2022-3-20)
|
||||
|
||||
- 修复注释空格的样式
|
||||
|
||||
## build 442 (2022-3-20)
|
||||
|
||||
- 修复打包模块后 `files` 的 autoload 项不能被解压和引入的 Bug
|
||||
|
||||
## build 441 (2022-3-20)
|
||||
|
||||
- 修复打包模块时命名空间与实际不一致的 Bug
|
||||
|
||||
## build 440 (2022-3-20)
|
||||
|
||||
- 新增方法宏(Macroable)
|
||||
|
||||
## build 439 (2022-3-19)
|
||||
|
||||
- 新增 PHP 8 Attribute 与注解同时支持的特性
|
||||
|
||||
## build 438 (2022-3-18)
|
||||
|
||||
- 修复 Response 类在 PHP 8.1 环境下的报错
|
||||
|
||||
## build 437 (2022-3-17)
|
||||
|
||||
- 修复 `ctx()` 可能会返回 null 的 Bug
|
||||
|
||||
## build 436 (2022-3-15)
|
||||
|
||||
- 新增 PHPStan 和 PHP CS Fixer 并优化全局代码
|
||||
|
||||
## build 435 (2022-3-13)
|
||||
|
||||
- 优化分离 WorkerManager 与 ProcessManager 的职责
|
||||
- 新增 Ctrl+C 一次无法停止框架时多次 Ctrl+C 后可强行杀掉所有进程的功能
|
||||
- `./zhamao server:stop` 新增参数 `--force`,使用 `SIGKILL` 强行杀掉所有进程
|
||||
- 新增 AnnotationParser 对 `autoload-dev` 项中的 `psr-4` 默认检索条件
|
||||
- 新增框架启动状态检测功能,如果已经启动了同样目录的框架,则会报错
|
||||
- 新增“强制启用轮询模式启动热更新”功能(参数 `--polling-watch`)
|
||||
- 修复与 PHP 8.1 的兼容性
|
||||
- 对 DaemonCommand 进行优化,与 ServerCommand 效果相同
|
||||
- 修复 `autoload`.`psr-4` 不存在时报错的 Bug
|
||||
- 新增框架停止时 Worker 退出回显状态码
|
||||
- 新增 inotify 判断模式,如果使用 `--watch` 检测到没有安装 inotify,则自动使用轮询模式
|
||||
|
||||
## build 434 (2022-1-8)
|
||||
|
||||
- 修复框架在 PHP 8.1 下运行时的一些问题
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
这里将会记录各个主版本的框架升级后,涉及 `global.php` 的更新日志,你可以根据这里描述的内容与你的旧配置文件进行合并。
|
||||
|
||||
## v2.7.0 (build 447)
|
||||
|
||||
- 新增 `$config['runtime']` 下的 `annotation_reader_ignore` 项。
|
||||
|
||||
## v2.6.6 (build 434)
|
||||
|
||||
- 新增 `$config['runtime']` 下的 `save_console_log_file` 项。
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
# 更新日志(v2 版本)
|
||||
|
||||
## v2.7.1(build 448)
|
||||
|
||||
> 更新时间:2022.3.20
|
||||
|
||||
- 加快 build 命令的执行速度,取消进度条和提升性能
|
||||
|
||||
## v2.7.0(build 447)
|
||||
|
||||
> 更新时间:2022.3.20
|
||||
|
||||
- 优化分离 WorkerManager 与 ProcessManager 的职责
|
||||
- 新增 Ctrl+C 一次无法停止框架时多次 Ctrl+C 后可强行杀掉所有进程的功能
|
||||
- `./zhamao server:stop` 新增参数 `--force`,使用 `SIGKILL` 强行杀掉所有进程
|
||||
- 新增 AnnotationParser 对 `autoload-dev` 项中的 `psr-4` 默认检索条件
|
||||
- 新增框架启动状态检测功能,如果已经启动了同样目录的框架,则会报错
|
||||
- 新增“强制启用轮询模式启动热更新”功能(参数 `--polling-watch`)
|
||||
- 修复与 PHP 8.1 的兼容性
|
||||
- 对 DaemonCommand 进行优化,与 ServerCommand 效果相同
|
||||
- 修复 `autoload`.`psr-4` 不存在时报错的 Bug
|
||||
- 新增框架停止时 Worker 退出回显状态码
|
||||
- 新增 inotify 判断模式,如果使用 `--watch` 检测到没有安装 inotify,则自动使用轮询模式
|
||||
- 新增 PHPStan 和 PHP CS Fixer 并优化全局代码
|
||||
- 修复 `ctx()` 可能会返回 null 的 Bug
|
||||
- 修复 Response 类在 PHP 8.1 环境下的报错
|
||||
- 新增 PHP 8 Attribute 与注解同时支持的特性
|
||||
- 新增方法宏(Macroable)
|
||||
- 修复打包模块时命名空间与实际不一致的 Bug
|
||||
- 修复打包模块后 `files` 的 autoload 项不能被解压和引入的 Bug
|
||||
- 修复注释空格的样式
|
||||
- 更改 `extra`.`exclude_annotate` 为 `zm`.`exclude-annotation-path` 项
|
||||
- 新增配置项 `runtime`.`annotation_reader_ignore`:支持注解解析器忽略注解的自定义
|
||||
- 新增 `./zhamao server` 下的 `--no-state-check` 参数,关闭“启动框架前的运行状态检查”功能
|
||||
|
||||
## v2.6.6(build 434)
|
||||
|
||||
> 更新时间:2022.1.8
|
||||
|
||||
10
mkdocs.yml
10
mkdocs.yml
@@ -16,11 +16,11 @@ theme:
|
||||
- navigation.tabs
|
||||
- navigation.sections
|
||||
extra_javascript:
|
||||
- https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js
|
||||
- javascripts/library/highlight.min.js
|
||||
- javascripts/config.js
|
||||
extra_css:
|
||||
- assets/css/extra.css
|
||||
- https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/default.min.css
|
||||
- assets/css/library/default.min.css
|
||||
plugins:
|
||||
- search:
|
||||
lang: ja
|
||||
@@ -39,7 +39,7 @@ extra:
|
||||
version:
|
||||
provider: mike
|
||||
|
||||
copyright: 'Copyright © 2019 - 2021 CrazyBot Team <span class="tx-switch">
|
||||
copyright: 'Copyright © 2019 - 2022 CrazyBot Team <span class="tx-switch">
|
||||
<button data-md-color-scheme="default"><code>默认模式</code></button>
|
||||
<button data-md-color-scheme="slate"><code>暗黑模式</code></button>
|
||||
</span>
|
||||
@@ -106,7 +106,7 @@ nav:
|
||||
- Console 终端: component/common/console.md
|
||||
- TaskWorker 管理: component/common/task-worker.md
|
||||
- Terminal 终端: component/common/remote-terminal.md
|
||||
- EventTracer 事件追踪器: component/comon/event-tracer.md
|
||||
- EventTracer 事件追踪器: component/common/event-tracer.md
|
||||
- HTTP 服务器工具类:
|
||||
- HTTP 和 WebSocket 客户端: component/http/zmrequest.md
|
||||
- HTTP 路由管理: component/http/route-manager.md
|
||||
@@ -125,6 +125,8 @@ nav:
|
||||
- 开发实战教程:
|
||||
- 接入 WebSocket 客户端: advanced/connect-ws-client.md
|
||||
- 编写管理员才能触发的功能: advanced/example/admin.md
|
||||
- 接入青云客聊天API: advanced/example/integrate-qingyunke-chatbot.md
|
||||
- 开发天气机器人: advanced/example/weather-bot.md
|
||||
- FAQ:
|
||||
- FAQ: faq/FAQ.md
|
||||
- 从 v1 升级: faq/to-v2.md
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Custom\Annotation;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\Interfaces\CustomAnnotation;
|
||||
@@ -11,10 +13,17 @@ use ZM\Annotation\Interfaces\CustomAnnotation;
|
||||
/**
|
||||
* Class CustomAnnotation
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class Example extends AnnotationBase implements CustomAnnotation
|
||||
{
|
||||
/** @var string */
|
||||
public $str = '';
|
||||
|
||||
public function __construct($str = '')
|
||||
{
|
||||
$this->str = $str;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ class Hello
|
||||
* 默认的图片监听路由对应目录,如需要使用可取消下面的注释,把上面的 /* 换成 /**
|
||||
* @OnStart(-1)
|
||||
*/
|
||||
//public function onStart() {
|
||||
// public function onStart() {
|
||||
// \ZM\Http\RouteManager::addStaticFileRoute("/images/", \ZM\Utils\DataProvider::getWorkingDir()."/zm_data/images/");
|
||||
//}
|
||||
// }
|
||||
|
||||
/**
|
||||
* 使用命令 .reload 发给机器人远程重载,注意将 user_id 换成你自己的 QQ
|
||||
@@ -98,7 +98,7 @@ class Hello
|
||||
$api = ''; // 请在这里填入你的图灵机器人的apikey
|
||||
if ($api === '') {
|
||||
return false;
|
||||
} //如果没有填入apikey则此功能关闭
|
||||
} // 如果没有填入apikey则此功能关闭
|
||||
if (($this->_running_annotation ?? null) instanceof CQCommand) {
|
||||
$msg = ctx()->getFullArg('我在!有什么事吗?');
|
||||
} else {
|
||||
@@ -109,7 +109,7 @@ class Hello
|
||||
return TuringAPI::getTuringMsg($msg, $user_id, $api);
|
||||
}
|
||||
QQBot::getInstance()->handle(ctx()->getData(), ctx()->getCache('level') + 1);
|
||||
//执行嵌套消息,递归层级+1
|
||||
// 执行嵌套消息,递归层级+1
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@ class TuringAPI
|
||||
public static function getTuringMsg($msg, $user_id, $api)
|
||||
{
|
||||
$origin = $msg;
|
||||
if (($cq = CQ::getCQ($msg)) !== null) {//如有CQ码则去除
|
||||
if (($cq = CQ::getCQ($msg)) !== null) {// 如有CQ码则去除
|
||||
if ($cq['type'] == 'image') {
|
||||
$url = $cq['params']['url'];
|
||||
$msg = str_replace(mb_substr($msg, $cq['start'], $cq['end'] - $cq['start'] + 1), '', $msg);
|
||||
}
|
||||
$msg = trim($msg);
|
||||
}
|
||||
//构建将要发送的json包给图灵
|
||||
// 构建将要发送的json包给图灵
|
||||
$content = [
|
||||
'reqType' => 0,
|
||||
'userInfo' => [
|
||||
@@ -64,11 +64,11 @@ class TuringAPI
|
||||
return '哎呀,我刚才有点走神了,可能忘记你说什么了,可以重说一遍吗';
|
||||
}
|
||||
Console::error(zm_internal_errcode('E00038') . "图灵机器人发送错误!\n错误原始内容:" . $origin . "\n来自:" . $user_id . "\n错误信息:" . $status);
|
||||
//echo json_encode($r, 128|256);
|
||||
// echo json_encode($r, 128|256);
|
||||
return '哎呀,我刚才有点走神了,要不一会儿换一种问题试试?';
|
||||
}
|
||||
$result = $api_return['results'];
|
||||
//Console::info(Console::setColor(json_encode($result, 128 | 256), "green"));
|
||||
// Console::info(Console::setColor(json_encode($result, 128 | 256), "green"));
|
||||
$final = '';
|
||||
foreach ($result as $v) {
|
||||
switch ($v['resultType']) {
|
||||
|
||||
@@ -8,9 +8,9 @@ use Closure;
|
||||
|
||||
abstract class AnnotationBase
|
||||
{
|
||||
public $method;
|
||||
public $method = '';
|
||||
|
||||
public $class;
|
||||
public $class = '';
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,8 @@ declare(strict_types=1);
|
||||
namespace ZM\Annotation;
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Koriym\Attributes\AttributeReader;
|
||||
use Koriym\Attributes\DualReader;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
@@ -46,7 +48,7 @@ class AnnotationParser
|
||||
public function __construct()
|
||||
{
|
||||
$this->start_time = microtime(true);
|
||||
//$this->loadAnnotationClasses();
|
||||
// $this->loadAnnotationClasses();
|
||||
$this->req_mapping[0] = [
|
||||
'id' => 0,
|
||||
'pid' => -1,
|
||||
@@ -63,15 +65,27 @@ class AnnotationParser
|
||||
foreach ($this->path_list as $path) {
|
||||
Console::debug('parsing annotation in ' . $path[0] . ':' . $path[1]);
|
||||
$all_class = ZMUtil::getClassesPsr4($path[0], $path[1]);
|
||||
$this->reader = new AnnotationReader();
|
||||
|
||||
$conf = ZMConfig::get('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);
|
||||
}
|
||||
}
|
||||
AnnotationReader::addGlobalIgnoredName('mixin');
|
||||
$this->reader = new DualReader(new AnnotationReader(), new AttributeReader());
|
||||
foreach ($all_class as $v) {
|
||||
Console::debug('正在检索 ' . $v);
|
||||
$reflection_class = new ReflectionClass($v);
|
||||
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
$class_annotations = $this->reader->getClassAnnotations($reflection_class);
|
||||
|
||||
// 这段为新加的:start
|
||||
//这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
|
||||
// 这里将每个类里面所有的类注解、方法注解通通加到一颗大树上,后期解析
|
||||
/*
|
||||
$annotation_map: {
|
||||
Module\Example\Hello: {
|
||||
@@ -99,7 +113,7 @@ class AnnotationParser
|
||||
foreach ($this->annotation_map[$v]['class_annotations'] as $vs) {
|
||||
$vs->class = $v;
|
||||
|
||||
//预处理1:将适用于每一个函数的注解到类注解重新注解到每个函数下面
|
||||
// 预处理1:将适用于每一个函数的注解到类注解重新注解到每个函数下面
|
||||
if ($vs instanceof ErgodicAnnotation) {
|
||||
foreach (($this->annotation_map[$v]['methods'] ?? []) as $method) {
|
||||
$copy = clone $vs;
|
||||
@@ -108,13 +122,13 @@ class AnnotationParser
|
||||
}
|
||||
}
|
||||
|
||||
//预处理2:处理 class 下面的注解
|
||||
// 预处理2:处理 class 下面的注解
|
||||
if ($vs instanceof Closed) {
|
||||
unset($this->annotation_map[$v]);
|
||||
continue 2;
|
||||
}
|
||||
if ($vs instanceof MiddlewareClass) {
|
||||
//注册中间件本身的类,标记到 middlewares 属性中
|
||||
// 注册中间件本身的类,标记到 middlewares 属性中
|
||||
Console::debug('正在注册中间件 ' . $reflection_class->getName());
|
||||
$rs = $this->registerMiddleware($vs, $reflection_class);
|
||||
$this->middlewares[$rs['name']] = $rs;
|
||||
@@ -123,7 +137,7 @@ class AnnotationParser
|
||||
|
||||
$inserted = [];
|
||||
|
||||
//预处理3:处理每个函数上面的特殊注解,就是需要操作一些东西的
|
||||
// 预处理3:处理每个函数上面的特殊注解,就是需要操作一些东西的
|
||||
foreach (($this->annotation_map[$v]['methods_annotations'] ?? []) as $method_name => $methods_annotations) {
|
||||
foreach ($methods_annotations as $method_anno) {
|
||||
/* @var AnnotationBase $method_anno */
|
||||
@@ -133,8 +147,7 @@ class AnnotationParser
|
||||
if (!isset($inserted[$v][$method_name])) {
|
||||
// 在这里在其他中间件前插入插入全局的中间件
|
||||
foreach ($middlewares as $middleware) {
|
||||
$mid_class = new Middleware();
|
||||
$mid_class->middleware = $middleware;
|
||||
$mid_class = new Middleware($middleware);
|
||||
$mid_class->class = $v;
|
||||
$mid_class->method = $method_name;
|
||||
$this->middleware_map[$v][$method_name][] = $mid_class;
|
||||
@@ -223,7 +236,7 @@ class AnnotationParser
|
||||
public function verifyMiddlewares()
|
||||
{
|
||||
if ((ZMConfig::get('global', 'runtime')['middleware_error_policy'] ?? 1) === 2) {
|
||||
//我承认套三层foreach很不优雅,但是这个会很快的。
|
||||
// 我承认套三层foreach很不优雅,但是这个会很快的。
|
||||
foreach ($this->middleware_map as $v) {
|
||||
foreach ($v as $vs) {
|
||||
foreach ($vs as $mid) {
|
||||
@@ -241,7 +254,7 @@ class AnnotationParser
|
||||
return microtime(true) - $this->start_time;
|
||||
}
|
||||
|
||||
//private function below
|
||||
// private function below
|
||||
|
||||
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class): array
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class CQAPIResponse
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class CQAPIResponse extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
@@ -20,4 +24,9 @@ class CQAPIResponse extends AnnotationBase
|
||||
* @Required()
|
||||
*/
|
||||
public $retcode;
|
||||
|
||||
public function __construct($retcode)
|
||||
{
|
||||
$this->retcode = $retcode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\Interfaces\Level;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQAfter
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class CQAfter extends AnnotationBase implements Level
|
||||
{
|
||||
/**
|
||||
@@ -23,6 +27,12 @@ class CQAfter extends AnnotationBase implements Level
|
||||
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($cq_event, $level = 20)
|
||||
{
|
||||
$this->cq_event = $cq_event;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -12,8 +14,10 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQBefore
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class CQBefore extends AnnotationBase implements Level
|
||||
{
|
||||
/**
|
||||
@@ -24,6 +28,12 @@ class CQBefore extends AnnotationBase implements Level
|
||||
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($cq_event, $level = 20)
|
||||
{
|
||||
$this->cq_event = $cq_event;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\Interfaces\Level;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQCommand
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class CQCommand extends AnnotationBase implements Level
|
||||
{
|
||||
/** @var string */
|
||||
@@ -51,6 +55,22 @@ class CQCommand extends AnnotationBase implements Level
|
||||
/** @var int */
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($match = '', $pattern = '', $regex = '', $start_with = '', $end_with = '', $keyword = '', $alias = [], $message_type = '', $user_id = 0, $group_id = 0, $discuss_id = 0, $level = 20)
|
||||
{
|
||||
$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->discuss_id = $discuss_id;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\Interfaces\Level;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQMessage
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class CQMessage extends AnnotationBase implements Level
|
||||
{
|
||||
/**
|
||||
@@ -38,6 +42,17 @@ class CQMessage extends AnnotationBase implements Level
|
||||
/** @var int */
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($message_type = '', $user_id = 0, $group_id = 0, $discuss_id = 0, $message = '', $raw_message = '', $level = 20)
|
||||
{
|
||||
$this->message_type = $message_type;
|
||||
$this->user_id = $user_id;
|
||||
$this->group_id = $group_id;
|
||||
$this->discuss_id = $discuss_id;
|
||||
$this->message = $message;
|
||||
$this->raw_message = $raw_message;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -12,18 +14,26 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQMetaEvent
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class CQMetaEvent extends AnnotationBase implements Level
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @Required()
|
||||
*/
|
||||
public $meta_event_type = '';
|
||||
public $meta_event_type;
|
||||
|
||||
/** @var int */
|
||||
public $level;
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($meta_event_type, $level = 20)
|
||||
{
|
||||
$this->meta_event_type = $meta_event_type;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\Interfaces\Level;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQNotice
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class CQNotice extends AnnotationBase implements Level
|
||||
{
|
||||
/** @var string */
|
||||
@@ -30,6 +34,15 @@ class CQNotice extends AnnotationBase implements Level
|
||||
/** @var int */
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($notice_type = '', $sub_type = '', $group_id = 0, $operator_id = 0, $level = 20)
|
||||
{
|
||||
$this->notice_type = $notice_type;
|
||||
$this->sub_type = $sub_type;
|
||||
$this->group_id = $group_id;
|
||||
$this->operator_id = $operator_id;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\CQ;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\Interfaces\Level;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\Interfaces\Level;
|
||||
/**
|
||||
* Class CQRequest
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class CQRequest extends AnnotationBase implements Level
|
||||
{
|
||||
/** @var string */
|
||||
@@ -30,6 +34,15 @@ class CQRequest extends AnnotationBase implements Level
|
||||
/** @var int */
|
||||
public $level = 20;
|
||||
|
||||
public function __construct($request_type = '', $sub_type = '', $user_id = 0, $comment = '', $level = 20)
|
||||
{
|
||||
$this->request_type = $request_type;
|
||||
$this->sub_type = $sub_type;
|
||||
$this->user_id = $user_id;
|
||||
$this->comment = $comment;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Command;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class TerminalCommand
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class TerminalCommand extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
@@ -27,4 +31,11 @@ class TerminalCommand extends AnnotationBase
|
||||
* @var string
|
||||
*/
|
||||
public $description = '';
|
||||
|
||||
public function __construct($command, $alias = '', $description = '')
|
||||
{
|
||||
$this->command = $command;
|
||||
$this->alias = $alias;
|
||||
$this->description = $description;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -12,8 +14,10 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
/**
|
||||
* Class Controller
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)]
|
||||
class Controller extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
@@ -21,4 +25,9 @@ class Controller extends AnnotationBase implements ErgodicAnnotation
|
||||
* @Required()
|
||||
*/
|
||||
public $prefix = '';
|
||||
|
||||
public function __construct(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class HandleAfter
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class HandleAfter extends AnnotationBase
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class HandleBefore
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class HandleBefore extends AnnotationBase
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use Exception;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,12 +13,19 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class HandleException
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class HandleException extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $class_name = Exception::class;
|
||||
|
||||
public function __construct($class_name = Exception::class)
|
||||
{
|
||||
$this->class_name = $class_name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -12,8 +14,10 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
|
||||
/**
|
||||
* Class Middleware
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_ALL)]
|
||||
class Middleware extends AnnotationBase implements ErgodicAnnotation
|
||||
{
|
||||
/**
|
||||
@@ -26,4 +30,10 @@ class Middleware extends AnnotationBase implements ErgodicAnnotation
|
||||
* @var string[]
|
||||
*/
|
||||
public $params = [];
|
||||
|
||||
public function __construct($middleware, $params = [])
|
||||
{
|
||||
$this->middleware = $middleware;
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class MiddlewareClass
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)]
|
||||
class MiddlewareClass extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
@@ -20,4 +24,9 @@ class MiddlewareClass extends AnnotationBase
|
||||
* @Required()
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class RequestMapping
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class RequestMapping extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
@@ -36,4 +40,12 @@ class RequestMapping extends AnnotationBase
|
||||
* @var array
|
||||
*/
|
||||
public $params = [];
|
||||
|
||||
public function __construct($route, $name = '', $request_method = [RequestMethod::GET, RequestMethod::POST], $params = [])
|
||||
{
|
||||
$this->route = $route;
|
||||
$this->name = $name;
|
||||
$this->request_method = $request_method;
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Http;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class RequestMethod
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class RequestMethod extends AnnotationBase
|
||||
{
|
||||
public const GET = 'GET';
|
||||
@@ -32,4 +38,9 @@ class RequestMethod extends AnnotationBase
|
||||
* @Required()
|
||||
*/
|
||||
public $method = self::GET;
|
||||
|
||||
public function __construct($method)
|
||||
{
|
||||
$this->method = $method;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Module;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class Closed
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_CLASS)]
|
||||
class Closed extends AnnotationBase
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,17 +4,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
* Class OnCloseEvent
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnCloseEvent extends OnSwooleEventBase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $connect_type = 'default';
|
||||
|
||||
public function __construct($connect_type = 'default', $rule = '', $level = 20)
|
||||
{
|
||||
$this->connect_type = $connect_type;
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
* @since 2.7.0
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnManagerStartEvent extends OnSwooleEventBase
|
||||
{
|
||||
public function __construct($rule = '', $level = 20)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("METHOD")
|
||||
* @NamedArgumentConstructor()
|
||||
* Class OnMessageEvent
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnMessageEvent extends OnSwooleEventBase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $connect_type = 'default';
|
||||
|
||||
public function __construct($connect_type = 'default', $rule = '', $level = 20)
|
||||
{
|
||||
$this->connect_type = $connect_type;
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
* Class OnOpenEvent
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnOpenEvent extends OnSwooleEventBase
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $connect_type = 'default';
|
||||
|
||||
public function __construct($connect_type = 'default', $rule = '', $level = 20)
|
||||
{
|
||||
$this->connect_type = $connect_type;
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,8 +13,10 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class OnPipeMessageEvent
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnPipeMessageEvent extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
@@ -20,4 +24,9 @@ class OnPipeMessageEvent extends AnnotationBase
|
||||
* @Required()
|
||||
*/
|
||||
public $action;
|
||||
|
||||
public function __construct($action)
|
||||
{
|
||||
$this->action = $action;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
* Class OnRequestEvent
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnRequestEvent extends OnSwooleEventBase
|
||||
{
|
||||
public function __construct($rule = '', $level = 20)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class OnSave
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnSave extends AnnotationBase
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class ZMSetup
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnSetup extends AnnotationBase
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,18 +4,27 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
|
||||
/**
|
||||
* Class OnWorkerStart
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnStart extends AnnotationBase
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $worker_id = 0;
|
||||
|
||||
public function __construct($worker_id = 0)
|
||||
{
|
||||
$this->worker_id = $worker_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* Class OnSwooleEvent
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnSwooleEvent extends OnSwooleEventBase
|
||||
{
|
||||
/**
|
||||
@@ -20,6 +24,13 @@ class OnSwooleEvent extends OnSwooleEventBase
|
||||
*/
|
||||
public $type;
|
||||
|
||||
public function __construct($type, $rule = '', $level = 20)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
|
||||
@@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -12,8 +14,10 @@ use ZM\Annotation\Interfaces\Rule;
|
||||
/**
|
||||
* Class OnTask
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnTask extends AnnotationBase implements Rule
|
||||
{
|
||||
/**
|
||||
@@ -27,6 +31,12 @@ class OnTask extends AnnotationBase implements Rule
|
||||
*/
|
||||
public $rule = '';
|
||||
|
||||
public function __construct($task_name, $rule = '')
|
||||
{
|
||||
$this->task_name = $task_name;
|
||||
$this->rule = $rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
@@ -4,13 +4,22 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Attribute;
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
|
||||
/**
|
||||
* Class OnTaskEvent
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
*/
|
||||
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
|
||||
class OnTaskEvent extends OnSwooleEventBase
|
||||
{
|
||||
public function __construct($rule = '', $level = 20)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,6 +12,7 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class OnTick
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("METHOD")
|
||||
* @since 1.2
|
||||
*/
|
||||
@@ -26,4 +28,10 @@ class OnTick extends AnnotationBase
|
||||
* @var int
|
||||
*/
|
||||
public $worker_id = 0;
|
||||
|
||||
public function __construct($tick_ms, $worker_id = 0)
|
||||
{
|
||||
$this->tick_ms = $tick_ms;
|
||||
$this->worker_id = $worker_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Annotation\Swoole;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\NamedArgumentConstructor;
|
||||
use Doctrine\Common\Annotations\Annotation\Required;
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
@@ -11,6 +12,7 @@ use ZM\Annotation\AnnotationBase;
|
||||
/**
|
||||
* Class SwooleHandler
|
||||
* @Annotation
|
||||
* @NamedArgumentConstructor()
|
||||
* @Target("ALL")
|
||||
*/
|
||||
class SwooleHandler extends AnnotationBase
|
||||
@@ -20,4 +22,13 @@ class SwooleHandler extends AnnotationBase
|
||||
* @Required()
|
||||
*/
|
||||
public $event;
|
||||
|
||||
/** @var string */
|
||||
public $params = '';
|
||||
|
||||
public function __construct($event, $params = '')
|
||||
{
|
||||
$this->event = $event;
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Command;
|
||||
|
||||
use ArrayIterator;
|
||||
use League\CLImate\CLImate;
|
||||
use Phar;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
@@ -66,7 +67,6 @@ class BuildCommand extends Command
|
||||
@unlink($target_dir . $filename);
|
||||
$phar = new Phar($target_dir . $filename);
|
||||
$phar->startBuffering();
|
||||
$climate = new CLImate();
|
||||
|
||||
$all = DataProvider::scanDirFiles(DataProvider::getSourceRootDir(), true, true);
|
||||
|
||||
@@ -76,19 +76,29 @@ class BuildCommand extends Command
|
||||
});
|
||||
|
||||
sort($all);
|
||||
$progress = $climate->progress()->total(count($all));
|
||||
|
||||
$archive_dir = DataProvider::getSourceRootDir();
|
||||
foreach ($all as $k => $v) {
|
||||
$phar->addFile($archive_dir . '/' . $v, $v);
|
||||
$progress->current($k + 1, 'Adding ' . $v);
|
||||
}
|
||||
$map = [];
|
||||
|
||||
if (class_exists('\\League\\CLImate\\CLImate')) {
|
||||
$climate = new CLImate();
|
||||
$progress = $climate->progress()->total(count($all));
|
||||
}
|
||||
foreach ($all as $k => $v) {
|
||||
$map[$v] = $archive_dir . '/' . $v;
|
||||
if (isset($progress)) {
|
||||
$progress->current($k + 1, 'Adding ' . $v);
|
||||
}
|
||||
}
|
||||
$this->output->write('<info>Building...</info>');
|
||||
$phar->buildFromIterator(new ArrayIterator($map));
|
||||
$phar->setStub(
|
||||
"#!/usr/bin/env php\n" .
|
||||
$phar->createDefaultStub(LOAD_MODE == 0 ? 'src/entry.php' : 'vendor/zhamao/framework/src/entry.php')
|
||||
);
|
||||
$phar->stopBuffering();
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln('Successfully built. Location: ' . $target_dir . "{$filename}");
|
||||
$this->output->writeln('<info>You may use `chmod +x server.phar` to let phar executable with `./` command</info>');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ class InitCommand extends Command
|
||||
$output->writeln('<info>Done!</info>');
|
||||
return 0;
|
||||
}
|
||||
if (LOAD_MODE === 2) { //从phar启动的框架包,初始化的模式
|
||||
if (LOAD_MODE === 2) { // 从phar启动的框架包,初始化的模式
|
||||
$phar_link = new Phar(__DIR__);
|
||||
$current_dir = pathinfo($phar_link->getPath())['dirname'];
|
||||
chdir($current_dir);
|
||||
|
||||
@@ -32,7 +32,7 @@ class ModuleListCommand extends Command
|
||||
exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
|
||||
}
|
||||
|
||||
//定义常量
|
||||
// 定义常量
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class ModulePackCommand extends Command
|
||||
exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
|
||||
}
|
||||
|
||||
//定义常量
|
||||
// 定义常量
|
||||
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
|
||||
|
||||
Console::init(
|
||||
|
||||
@@ -41,7 +41,7 @@ class ModuleUnpackCommand extends Command
|
||||
exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
|
||||
}
|
||||
|
||||
//定义常量
|
||||
// 定义常量
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class PureHttpCommand extends Command
|
||||
'document_index' => $index,
|
||||
]
|
||||
);
|
||||
//echo "\r" . Coroutine::stats()["coroutine_peak_num"];
|
||||
// echo "\r" . Coroutine::stats()["coroutine_peak_num"];
|
||||
});
|
||||
$server->on('start', function ($server) {
|
||||
Process::signal(SIGINT, function () use ($server) {
|
||||
|
||||
@@ -46,6 +46,7 @@ class RunServerCommand extends Command
|
||||
new InputOption('preview', null, null, '只显示参数,不启动服务器'),
|
||||
new InputOption('force-load-module', null, InputOption::VALUE_OPTIONAL, '强制打包状态下加载模块(使用英文逗号分割多个)'),
|
||||
new InputOption('polling-watch', null, null, '强制启用轮询模式监听'),
|
||||
new InputOption('no-state-check', null, null, '关闭启动前框架运行状态检查'),
|
||||
]);
|
||||
$this->setDescription('Run zhamao-framework | 启动框架');
|
||||
$this->setHelp('直接运行可以启动');
|
||||
@@ -60,10 +61,12 @@ class RunServerCommand extends Command
|
||||
}
|
||||
}
|
||||
$state = Framework::getProcessState(ZM_PROCESS_MASTER);
|
||||
if (is_array($state) && posix_getsid($state['pid'] ?? -1) !== false) {
|
||||
$output->writeln("<error>检测到已经在 pid: {$state['pid']} 进程启动了框架!</error>");
|
||||
$output->writeln('<error>不可以同时启动两个框架!</error>');
|
||||
return 1;
|
||||
if (!$input->getOption('no-state-check')) {
|
||||
if (is_array($state) && posix_getsid($state['pid'] ?? -1) !== false) {
|
||||
$output->writeln("<error>检测到已经在 pid: {$state['pid']} 进程启动了框架!</error>");
|
||||
$output->writeln('<error>不可以同时启动两个框架!</error>');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
(new Framework($input->getOptions()))->start();
|
||||
return 0;
|
||||
|
||||
@@ -28,9 +28,9 @@ use ZM\Exception\InitException;
|
||||
|
||||
class ConsoleApplication extends Application
|
||||
{
|
||||
public const VERSION_ID = 436;
|
||||
public const VERSION_ID = 448;
|
||||
|
||||
public const VERSION = '2.7.0-beta2';
|
||||
public const VERSION = '2.7.1';
|
||||
|
||||
private static $obj;
|
||||
|
||||
@@ -87,11 +87,11 @@ class ConsoleApplication extends Application
|
||||
new DaemonStatusCommand(),
|
||||
new DaemonReloadCommand(),
|
||||
new DaemonStopCommand(),
|
||||
new RunServerCommand(), //运行主服务的指令控制器
|
||||
new RunServerCommand(), // 运行主服务的指令控制器
|
||||
new ServerStatusCommand(),
|
||||
new ServerStopCommand(),
|
||||
new ServerReloadCommand(),
|
||||
new PureHttpCommand(), //纯HTTP服务器指令
|
||||
new PureHttpCommand(), // 纯HTTP服务器指令
|
||||
new SystemdGenerateCommand(),
|
||||
]);
|
||||
if (LOAD_MODE === 1) {
|
||||
|
||||
@@ -123,7 +123,7 @@ class DB
|
||||
if ($result !== true) {
|
||||
SqlPoolStorage::$sql_pool->putConnection(null);
|
||||
throw new DBException("语句[{$line}]错误!" . $ps->errorInfo()[2]);
|
||||
//echo json_encode(debug_backtrace(), 128 | 256);
|
||||
// echo json_encode(debug_backtrace(), 128 | 256);
|
||||
}
|
||||
SqlPoolStorage::$sql_pool->putConnection($conn);
|
||||
return $ps->fetchAll($fetch_mode);
|
||||
|
||||
@@ -67,7 +67,7 @@ class Table
|
||||
public function statement()
|
||||
{
|
||||
$this->cache = [];
|
||||
//TODO: 无返回的statement语句
|
||||
// TODO: 无返回的statement语句
|
||||
}
|
||||
|
||||
public function paintWhereSQL($rule, $operator)
|
||||
|
||||
@@ -19,15 +19,15 @@ use ZM\Utils\ZMUtil;
|
||||
|
||||
class EventDispatcher
|
||||
{
|
||||
public const STATUS_NORMAL = 0; //正常结束
|
||||
public const STATUS_NORMAL = 0; // 正常结束
|
||||
|
||||
public const STATUS_INTERRUPTED = 1; //被interrupt了,不管在什么地方
|
||||
public const STATUS_INTERRUPTED = 1; // 被interrupt了,不管在什么地方
|
||||
|
||||
public const STATUS_EXCEPTION = 2; //执行过程中抛出了异常
|
||||
public const STATUS_EXCEPTION = 2; // 执行过程中抛出了异常
|
||||
|
||||
public const STATUS_BEFORE_FAILED = 3; //中间件HandleBefore返回了false,所以不执行此方法
|
||||
public const STATUS_BEFORE_FAILED = 3; // 中间件HandleBefore返回了false,所以不执行此方法
|
||||
|
||||
public const STATUS_RULE_FAILED = 4; //判断事件执行的规则函数判定为false,所以不执行此方法
|
||||
public const STATUS_RULE_FAILED = 4; // 判断事件执行的规则函数判定为false,所以不执行此方法
|
||||
|
||||
/** @var int */
|
||||
public $status = self::STATUS_NORMAL;
|
||||
@@ -133,7 +133,7 @@ class EventDispatcher
|
||||
if ($this->status === self::STATUS_RULE_FAILED) {
|
||||
$this->status = self::STATUS_NORMAL;
|
||||
}
|
||||
//TODO:没有过滤before的false,可能会导致一些问题,先观望一下
|
||||
// TODO:没有过滤before的false,可能会导致一些问题,先观望一下
|
||||
} catch (InterruptException $e) {
|
||||
$this->store = $e->return_var;
|
||||
$this->status = self::STATUS_INTERRUPTED;
|
||||
@@ -200,7 +200,7 @@ class EventDispatcher
|
||||
}
|
||||
$middleware_obj = EventManager::$middlewares[$middleware->middleware];
|
||||
$before = $middleware_obj['class'];
|
||||
//var_dump($middleware_obj);
|
||||
// var_dump($middleware_obj);
|
||||
$r[$k] = new $before();
|
||||
$r[$k]->class = $q_c;
|
||||
$r[$k]->method = $q_f;
|
||||
|
||||
@@ -61,7 +61,7 @@ class EventManager
|
||||
if (server()->worker_id !== $vss->worker_id && $vss->worker_id != -1) {
|
||||
return;
|
||||
}
|
||||
//echo server()->worker_id.PHP_EOL;
|
||||
// echo server()->worker_id.PHP_EOL;
|
||||
$plain_class = $vss->class;
|
||||
Console::debug('Added Middleware-based timer: ' . $plain_class . ' -> ' . $vss->method);
|
||||
Timer::tick($vss->tick_ms, function () use ($vss, $dispatcher) {
|
||||
|
||||
@@ -30,7 +30,10 @@ class EventTracer
|
||||
public static function getCurrentEventMiddlewares()
|
||||
{
|
||||
$current_event = self::getCurrentEvent();
|
||||
if (!isset($current_event->class, $current_event->method)) {
|
||||
if (empty($current_event->class)) {
|
||||
return null;
|
||||
}
|
||||
if (empty($current_event->method)) {
|
||||
return null;
|
||||
}
|
||||
return EventManager::$middleware_map[$current_event->class][$current_event->method] ?? [];
|
||||
|
||||
@@ -52,10 +52,10 @@ class OnMessage implements SwooleEvent
|
||||
return false;
|
||||
});
|
||||
try {
|
||||
//$starttime = microtime(true);
|
||||
// $starttime = microtime(true);
|
||||
$dispatcher1->dispatchEvents($conn);
|
||||
$dispatcher->dispatchEvents($conn);
|
||||
//Console::success("Used ".round((microtime(true) - $starttime) * 1000, 3)." ms!");
|
||||
// Console::success("Used ".round((microtime(true) - $starttime) * 1000, 3)." ms!");
|
||||
} catch (Exception $e) {
|
||||
$error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
|
||||
Console::error(zm_internal_errcode('E00017') . 'Uncaught exception ' . get_class($e) . ' when calling "message": ' . $error_msg);
|
||||
|
||||
@@ -39,7 +39,7 @@ class OnRequest implements SwooleEvent
|
||||
|
||||
$dis1 = new EventDispatcher(OnRequestEvent::class);
|
||||
$dis1->setRuleFunction(function ($v) {
|
||||
return eval('return ' . $v->getRule() . ';') ? true : false;
|
||||
return (bool) eval('return ' . $v->getRule() . ';');
|
||||
});
|
||||
|
||||
$dis = new EventDispatcher(OnSwooleEvent::class);
|
||||
@@ -61,13 +61,12 @@ class OnRequest implements SwooleEvent
|
||||
if ($result === true) {
|
||||
ctx()->setCache('params', $params);
|
||||
$dispatcher = new EventDispatcher(RequestMapping::class);
|
||||
$div = new RequestMapping();
|
||||
$div->route = $node['route'];
|
||||
$div = new RequestMapping($node['route']);
|
||||
$div->params = $params;
|
||||
$div->method = $node['method'];
|
||||
$div->request_method = $node['request_method'];
|
||||
$div->class = $node['class'];
|
||||
//Console::success("正在执行路由:".$node["method"]);
|
||||
// Console::success("正在执行路由:".$node["method"]);
|
||||
$dispatcher->dispatchEvent($div, null, $params, $request, $response);
|
||||
if (is_string($dispatcher->store) && !$response->isEnd()) {
|
||||
$response->end($dispatcher->store);
|
||||
@@ -75,7 +74,7 @@ class OnRequest implements SwooleEvent
|
||||
}
|
||||
}
|
||||
if (!$response->isEnd()) {
|
||||
//Console::warning('返回了404');
|
||||
// Console::warning('返回了404');
|
||||
HttpUtil::responseCodePage($response, 404);
|
||||
}
|
||||
} catch (InterruptException $e) {
|
||||
|
||||
@@ -66,7 +66,7 @@ class OnWorkerStart implements SwooleEvent
|
||||
} elseif (!isset($error['type'])) {
|
||||
return;
|
||||
}
|
||||
//DataProvider::saveBuffer();
|
||||
// DataProvider::saveBuffer();
|
||||
/* @var Server $server */
|
||||
if (server() === null) {
|
||||
$server->shutdown();
|
||||
@@ -77,10 +77,10 @@ class OnWorkerStart implements SwooleEvent
|
||||
|
||||
Console::verbose("Worker #{$server->worker_id} starting");
|
||||
Framework::$server = $server;
|
||||
//ZMBuf::resetCache(); //清空变量缓存
|
||||
//ZMBuf::set("wait_start", []); //添加队列,在workerStart运行完成前先让其他协程等待执行
|
||||
// ZMBuf::resetCache(); //清空变量缓存
|
||||
// ZMBuf::set("wait_start", []); //添加队列,在workerStart运行完成前先让其他协程等待执行
|
||||
|
||||
//TODO: 单独抽出来MySQL和Redis连接池
|
||||
// TODO: 单独抽出来MySQL和Redis连接池
|
||||
$this->initMySQLPool();
|
||||
|
||||
// 开箱即用的Redis
|
||||
@@ -93,9 +93,9 @@ class OnWorkerStart implements SwooleEvent
|
||||
}
|
||||
}
|
||||
|
||||
$this->loadAnnotations(); //加载composer资源、phar外置包、注解解析注册等
|
||||
$this->loadAnnotations(); // 加载composer资源、phar外置包、注解解析注册等
|
||||
|
||||
EventManager::registerTimerTick(); //启动计时器
|
||||
EventManager::registerTimerTick(); // 启动计时器
|
||||
set_coroutine_params(['server' => $server, 'worker_id' => $worker_id]);
|
||||
$dispatcher = new EventDispatcher(OnStart::class);
|
||||
$dispatcher->setRuleFunction(function ($v) {
|
||||
@@ -151,14 +151,15 @@ class OnWorkerStart implements SwooleEvent
|
||||
if (Framework::$instant_mode) {
|
||||
goto skip;
|
||||
}
|
||||
//加载各个模块的注解类,以及反射
|
||||
// 加载各个模块的注解类,以及反射
|
||||
Console::debug('Mapping annotations');
|
||||
$parser = new AnnotationParser();
|
||||
$composer = json_decode(file_get_contents(DataProvider::getSourceRootDir() . '/composer.json'), true);
|
||||
$merge = array_merge($composer['autoload']['psr-4'] ?? [], $composer['autoload-dev']['psr-4'] ?? []);
|
||||
$exclude_annotations = array_merge($composer['extra']['exclude_annotate'] ?? [], $composer['extra']['zm']['exclude-annotation-path'] ?? []);
|
||||
foreach ($merge as $k => $v) {
|
||||
if (is_dir(DataProvider::getSourceRootDir() . '/' . $v)) {
|
||||
if (in_array(trim($k, '\\') . '\\', $composer['extra']['exclude_annotate'] ?? [])) {
|
||||
if (in_array(trim($k, '\\') . '\\', $exclude_annotations)) {
|
||||
continue;
|
||||
}
|
||||
if (trim($k, '\\') == 'ZM') {
|
||||
@@ -187,16 +188,16 @@ class OnWorkerStart implements SwooleEvent
|
||||
}
|
||||
|
||||
$parser->registerMods();
|
||||
EventManager::loadEventByParser($parser); //加载事件
|
||||
EventManager::loadEventByParser($parser); // 加载事件
|
||||
|
||||
skip:
|
||||
//加载自定义的全局函数
|
||||
// 加载自定义的全局函数
|
||||
Console::debug('Loading context class...');
|
||||
$context_class = ZMConfig::get('global', 'context_class');
|
||||
if (!is_a($context_class, ContextInterface::class, true)) {
|
||||
throw new ZMKnownException('E00032', 'Context class must implemented from ContextInterface!');
|
||||
}
|
||||
//加载插件
|
||||
// 加载插件
|
||||
$obb_onebot = ZMConfig::get('global', 'onebot') ??
|
||||
ZMConfig::get('global', 'modules')['onebot'] ??
|
||||
['status' => true, 'single_bot_mode' => false, 'message_level' => 99999];
|
||||
@@ -251,7 +252,7 @@ class OnWorkerStart implements SwooleEvent
|
||||
if (!empty($real_conf)) {
|
||||
Console::info('Connecting to MySQL pool');
|
||||
ob_start();
|
||||
phpinfo(); //这个phpinfo是有用的,不能删除
|
||||
phpinfo(); // 这个phpinfo是有用的,不能删除
|
||||
$str = ob_get_clean();
|
||||
$str = explode("\n", $str);
|
||||
foreach ($str as $v) {
|
||||
|
||||
@@ -4,6 +4,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
class InvalidArgumentException extends ZMException
|
||||
{
|
||||
public function __construct($message = '', $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(zm_internal_errcode('E00074') . $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
|
||||
15
src/ZM/Exception/MethodNotFoundException.php
Normal file
15
src/ZM/Exception/MethodNotFoundException.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
class MethodNotFoundException extends ZMException
|
||||
{
|
||||
public function __construct($message = '', $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(zm_internal_errcode('E00073') . $message, $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ class Framework
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//定义常量
|
||||
// 定义常量
|
||||
include_once 'global_defines.php';
|
||||
|
||||
try {
|
||||
@@ -144,9 +144,9 @@ class Framework
|
||||
$this->server_set['log_level'] = SWOOLE_LOG_DEBUG;
|
||||
$add_port = ZMConfig::get('global', 'remote_terminal')['status'] ?? false;
|
||||
|
||||
//if ($instant_mode) {
|
||||
// if ($instant_mode) {
|
||||
$this->loadServerEvents();
|
||||
//}
|
||||
// }
|
||||
|
||||
$this->parseCliArgs(self::$argv, $add_port);
|
||||
|
||||
@@ -288,7 +288,7 @@ class Framework
|
||||
|
||||
$port->on('close', function ($serv, $fd) {
|
||||
ManagerGM::popConnect($fd);
|
||||
//echo "Client: Close.\n";
|
||||
// echo "Client: Close.\n";
|
||||
});
|
||||
}
|
||||
|
||||
@@ -301,9 +301,9 @@ class Framework
|
||||
// 注册 Swoole Server 的事件
|
||||
$this->registerServerEvents();
|
||||
$r = ZMConfig::get('global', 'light_cache') ?? [
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'size' => 512, // 最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, // 单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, // Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900,
|
||||
];
|
||||
@@ -520,13 +520,13 @@ class Framework
|
||||
if (!isset($line_width[$current_line])) {
|
||||
$line_width[$current_line] = $max_border - 2;
|
||||
}
|
||||
//Console::info("行宽[$current_line]:".$line_width[$current_line]);
|
||||
// Console::info("行宽[$current_line]:".$line_width[$current_line]);
|
||||
if ($max_border >= 57) { // 很宽的时候,一行能放两个短行
|
||||
if ($line_width[$current_line] == ($max_border - 2)) { //空行
|
||||
if ($line_width[$current_line] == ($max_border - 2)) { // 空行
|
||||
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
||||
} else { // 不是空行,已经有东西了
|
||||
$tmp_line = $k . ': ' . $v;
|
||||
//Console::info("[$current_line]即将插入后面的东西[".$tmp_line."]");
|
||||
// Console::info("[$current_line]即将插入后面的东西[".$tmp_line."]");
|
||||
if (strlen($tmp_line) > $line_width[$current_line]) { // 地方不够,另起一行
|
||||
$line_data[$current_line] = str_replace('| ', '', $line_data[$current_line]);
|
||||
++$current_line;
|
||||
@@ -725,8 +725,8 @@ class Framework
|
||||
break;
|
||||
case 'show-php-ver':
|
||||
default:
|
||||
//Console::info("Calculating ".$x);
|
||||
//dump($y);
|
||||
// Console::info("Calculating ".$x);
|
||||
// dump($y);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -742,8 +742,8 @@ class Framework
|
||||
private static function writeNoDouble($k, $v, &$line_data, &$line_width, &$current_line, $colorful, $max_border)
|
||||
{
|
||||
$tmp_line = $k . ': ' . $v;
|
||||
//Console::info("写入[".$tmp_line."]");
|
||||
if (strlen($tmp_line) > $line_width[$current_line]) { //输出的内容太多了,以至于一行都放不下一个,要折行
|
||||
// Console::info("写入[".$tmp_line."]");
|
||||
if (strlen($tmp_line) > $line_width[$current_line]) { // 输出的内容太多了,以至于一行都放不下一个,要折行
|
||||
$title_strlen = strlen($k . ': ');
|
||||
$content_len = $line_width[$current_line] - $title_strlen;
|
||||
|
||||
@@ -769,7 +769,7 @@ class Framework
|
||||
++$current_line;
|
||||
} while ($rest > $max_border - 2); // 循环,直到放完
|
||||
} else { // 不需要折行
|
||||
//Console::info("不需要折行");
|
||||
// Console::info("不需要折行");
|
||||
$line_data[$current_line] = ' ' . $k . ': ';
|
||||
if ($colorful) {
|
||||
$line_data[$current_line] .= TermColor::color8(32);
|
||||
@@ -781,10 +781,10 @@ class Framework
|
||||
|
||||
if ($max_border >= 57) {
|
||||
if (strlen($tmp_line) >= intval(($max_border - 2) / 2)) { // 不需要折行,直接输出一个转下一行
|
||||
//Console::info("不需要折行,直接输出一个转下一行");
|
||||
// Console::info("不需要折行,直接输出一个转下一行");
|
||||
++$current_line;
|
||||
} else { // 输出很小,写到前面并分片
|
||||
//Console::info("输出很小,写到前面并分片");
|
||||
// Console::info("输出很小,写到前面并分片");
|
||||
$space = intval($max_border / 2) - 2 - strlen($tmp_line);
|
||||
$line_data[$current_line] .= str_pad('', $space);
|
||||
$line_data[$current_line] .= '| '; // 添加分片
|
||||
|
||||
@@ -56,50 +56,32 @@ class Response
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @param $expires
|
||||
* @param $path
|
||||
* @param $domain
|
||||
* @param $secure
|
||||
* @param $httponly
|
||||
* @param $samesite
|
||||
* @param mixed ...$params
|
||||
* @return mixed
|
||||
*/
|
||||
public function cookie($name, $value = null, $expires = null, $path = null, $domain = null, $secure = null, $httponly = null, $samesite = null)
|
||||
public function cookie($name, ...$params)
|
||||
{
|
||||
return $this->response->rawcookie($name, $value, $expires, $path, $domain, $secure, $httponly, $samesite);
|
||||
return empty($params) ? $this->response->rawcookie($name) : $this->response->rawcookie($name, ...$params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @param $expires
|
||||
* @param $path
|
||||
* @param $domain
|
||||
* @param $secure
|
||||
* @param $httponly
|
||||
* @param $samesite
|
||||
* @param mixed ...$params
|
||||
* @param mixed $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function setCookie($name, $value = null, $expires = null, $path = null, $domain = null, $secure = null, $httponly = null, $samesite = null)
|
||||
public function setCookie($name, ...$params)
|
||||
{
|
||||
return $this->response->setCookie($name, $value, $expires, $path, $domain, $secure, $httponly, $samesite);
|
||||
return empty($params) ? $this->response->rawcookie($name) : $this->response->setCookie($name, ...$params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @param $expires
|
||||
* @param $path
|
||||
* @param $domain
|
||||
* @param $secure
|
||||
* @param $httponly
|
||||
* @param $samesite
|
||||
* @param mixed ...$params
|
||||
* @param mixed $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function rawcookie($name, $value = null, $expires = null, $path = null, $domain = null, $secure = null, $httponly = null, $samesite = null)
|
||||
public function rawcookie($name, ...$params)
|
||||
{
|
||||
return $this->response->rawcookie($name, $value, $expires, $path, $domain, $secure, $httponly, $samesite);
|
||||
return empty($params) ? $this->response->rawcookie($name) : $this->response->rawcookie($name, ...$params);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,11 +89,11 @@ class Response
|
||||
* @param $reason
|
||||
* @return mixed
|
||||
*/
|
||||
public function status($http_code, $reason = null)
|
||||
public function status($http_code, ...$params)
|
||||
{
|
||||
$this->status_code = $http_code;
|
||||
if (!$this->is_end) {
|
||||
return $this->response->status($http_code, $reason);
|
||||
return empty($params) ? $this->response->status($http_code) : $this->response->status($http_code, ...$params);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -126,10 +108,10 @@ class Response
|
||||
* @param $reason
|
||||
* @return mixed
|
||||
*/
|
||||
public function setStatusCode($http_code, $reason = null)
|
||||
public function setStatusCode($http_code, ...$params)
|
||||
{
|
||||
if (!$this->is_end) {
|
||||
return $this->response->setStatusCode($http_code, $reason);
|
||||
return empty($params) ? $this->response->status($http_code) : $this->response->status($http_code, ...$params);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ use ZM\Utils\ZMUtil;
|
||||
*/
|
||||
class ModulePacker
|
||||
{
|
||||
public const ZM_MODULE_PACKER_VERSION = '1.0';
|
||||
public const ZM_MODULE_PACKER_VERSION = '1.1';
|
||||
|
||||
/** @var array */
|
||||
private $module = [];
|
||||
@@ -114,11 +114,11 @@ class ModulePacker
|
||||
$this->phar->startBuffering();
|
||||
Console::info('模块输出文件:' . $this->filename);
|
||||
|
||||
$this->addFiles(); //添加文件
|
||||
$this->addLightCacheStore(); //保存light-cache-store指定的项
|
||||
$this->addModuleConfig(); //生成module-config.json
|
||||
$this->addZMDataFiles(); //添加需要保存的zm_data下的目录或文件
|
||||
$this->addEntry(); //生成模块的入口文件module_entry.php
|
||||
$this->addFiles(); // 添加文件
|
||||
$this->addLightCacheStore(); // 保存light-cache-store指定的项
|
||||
$this->addModuleConfig(); // 生成module-config.json
|
||||
$this->addZMDataFiles(); // 添加需要保存的zm_data下的目录或文件
|
||||
$this->addEntry(); // 生成模块的入口文件module_entry.php
|
||||
|
||||
$this->phar->stopBuffering();
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class ModulePacker
|
||||
if ($pos === 0) {
|
||||
$path_value = substr($this->module['module-path'], strlen(DataProvider::getSourceRootDir() . '/'));
|
||||
} else {
|
||||
throw new ModulePackException(zm_internal_errcode('E99999')); //未定义的错误
|
||||
throw new ModulePackException(zm_internal_errcode('E99999')); // 未定义的错误
|
||||
}
|
||||
return ZMUtil::getClassesPsr4($this->module['module-path'], $this->module['namespace'], null, $path_value);
|
||||
}
|
||||
@@ -158,7 +158,7 @@ class ModulePacker
|
||||
}
|
||||
}
|
||||
foreach (($composer['autoload']['files'] ?? []) as $v) {
|
||||
if (strcmp($path, $v) === 0) {
|
||||
if (strpos($v, $path) === 0) {
|
||||
$item['files'][] = $v;
|
||||
}
|
||||
}
|
||||
@@ -174,9 +174,9 @@ class ModulePacker
|
||||
if (isset($this->module['light-cache-store'])) {
|
||||
$store = [];
|
||||
$r = ZMConfig::get('global', 'light_cache') ?? [
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'size' => 512, // 最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, // 单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, // Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900,
|
||||
];
|
||||
@@ -202,7 +202,7 @@ class ModulePacker
|
||||
'module-packer-version' => self::ZM_MODULE_PACKER_VERSION,
|
||||
'module-root-path' => $this->getRelativePath($this->module['module-path']),
|
||||
'namespace' => $this->module['namespace'],
|
||||
'autoload-psr-4' => $this->generatePharAutoload(),
|
||||
'hotload-psr-4' => $this->generatePharAutoload(),
|
||||
'unpack' => [
|
||||
'composer-autoload-items' => $this->getComposerAutoloadItems(),
|
||||
'global-config-override' => $this->module['global-config-override'] ?? false,
|
||||
@@ -210,6 +210,9 @@ class ModulePacker
|
||||
'allow-hotload' => $this->module['allow-hotload'] ?? false,
|
||||
'pack-time' => time(),
|
||||
];
|
||||
if (isset($stub_values['unpack']['composer-autoload-items']['files'])) {
|
||||
$stub_values['hotload-files'] = $stub_values['unpack']['composer-autoload-items']['files'];
|
||||
}
|
||||
$this->phar->addFromString('zmplugin.json', json_encode($stub_values, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
$this->module_config = $stub_values;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ class ModuleUnpacker
|
||||
|
||||
/**
|
||||
* 解包模块
|
||||
* @param bool $ignore_depends
|
||||
*
|
||||
* @param mixed $ignore_depends
|
||||
* @throws ModulePackException
|
||||
* @throws ZMException
|
||||
*/
|
||||
@@ -61,7 +62,8 @@ class ModuleUnpacker
|
||||
|
||||
/**
|
||||
* 检查模块依赖关系
|
||||
* @param bool $ignore_depends
|
||||
*
|
||||
* @param mixed $ignore_depends
|
||||
* @throws ModulePackException
|
||||
* @throws ZMException
|
||||
*/
|
||||
@@ -125,8 +127,8 @@ class ModuleUnpacker
|
||||
throw new ModulePackException(zm_internal_errcode('E00068'));
|
||||
}
|
||||
$composer = json_decode(file_get_contents($composer_file), true);
|
||||
if (isset($this->module_config['composer-extend-autoload'])) {
|
||||
$autoload = $this->module_config['composer-extend-autoload'];
|
||||
if (isset($this->module_config['unpack']['composer-autoload-items'])) {
|
||||
$autoload = $this->module_config['unpack']['composer-autoload-items'];
|
||||
if (isset($autoload['psr-4'])) {
|
||||
Console::info('Adding extended autoload psr-4 for composer');
|
||||
$composer['autoload']['psr-4'] = isset($composer['autoload']['psr-4']) ? array_merge($composer['autoload']['psr-4'], $autoload['psr-4']) : $autoload['psr-4'];
|
||||
@@ -136,6 +138,7 @@ class ModuleUnpacker
|
||||
$composer['autoload']['files'] = isset($composer['autoload']['files']) ? array_merge($composer['autoload']['files'], $autoload['files']) : $autoload['files'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($this->module_config['composer-extend-require'])) {
|
||||
foreach ($this->module_config['composer-extend-require'] as $k => $v) {
|
||||
Console::info('Adding extended required composer library: ' . $k);
|
||||
@@ -172,9 +175,9 @@ class ModuleUnpacker
|
||||
private function copyLightCacheStore($override)
|
||||
{
|
||||
$r = ZMConfig::get('global', 'light_cache') ?? [
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'size' => 512, // 最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, // 单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, // Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900,
|
||||
];
|
||||
|
||||
@@ -47,16 +47,16 @@ class QQBot
|
||||
}
|
||||
set_coroutine_params(['data' => $data]);
|
||||
if (isset($data['post_type'])) {
|
||||
//echo TermColor::ITALIC.json_encode($data, 128|256).TermColor::RESET.PHP_EOL;
|
||||
// echo TermColor::ITALIC.json_encode($data, 128|256).TermColor::RESET.PHP_EOL;
|
||||
ctx()->setCache('level', $level);
|
||||
//Console::debug("Calling CQ Event from fd=" . ctx()->getConnection()->getFd());
|
||||
// Console::debug("Calling CQ Event from fd=" . ctx()->getConnection()->getFd());
|
||||
if ($data['post_type'] != 'meta_event') {
|
||||
$r = $this->dispatchBeforeEvents($data, 'pre'); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === 'block') {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
//Console::warning("最上数据包:".json_encode($data));
|
||||
// Console::warning("最上数据包:".json_encode($data));
|
||||
}
|
||||
if (isset($data['echo']) || isset($data['post_type'])) {
|
||||
if (CoMessage::resumeByWS()) {
|
||||
@@ -134,10 +134,10 @@ class QQBot
|
||||
*/
|
||||
private function dispatchEvents($data)
|
||||
{
|
||||
//Console::warning("最xia数据包:".json_encode($data));
|
||||
// Console::warning("最xia数据包:".json_encode($data));
|
||||
switch ($data['post_type']) {
|
||||
case 'message':
|
||||
//分发CQCommand事件
|
||||
// 分发CQCommand事件
|
||||
$dispatcher = new EventDispatcher(CQCommand::class);
|
||||
$dispatcher->setReturnFunction(function ($result) {
|
||||
if (is_string($result)) {
|
||||
@@ -170,7 +170,7 @@ class QQBot
|
||||
}
|
||||
}
|
||||
|
||||
//分发CQMessage事件
|
||||
// 分发CQMessage事件
|
||||
$msg_dispatcher = new EventDispatcher(CQMessage::class);
|
||||
$msg_dispatcher->setRuleFunction(function ($v) {
|
||||
return ($v->message == '' || ($v->message == ctx()->getStringMessage()))
|
||||
@@ -187,12 +187,12 @@ class QQBot
|
||||
$msg_dispatcher->dispatchEvents(ctx()->getMessage());
|
||||
return;
|
||||
case 'meta_event':
|
||||
//Console::success("当前数据包:".json_encode(ctx()->getData()));
|
||||
// Console::success("当前数据包:".json_encode(ctx()->getData()));
|
||||
$dispatcher = new EventDispatcher(CQMetaEvent::class);
|
||||
$dispatcher->setRuleFunction(function (CQMetaEvent $v) {
|
||||
return $v->meta_event_type == '' || ($v->meta_event_type != '' && $v->meta_event_type == ctx()->getData()['meta_event_type']);
|
||||
});
|
||||
//eval(BP);
|
||||
// eval(BP);
|
||||
$dispatcher->dispatchEvents(ctx()->getData());
|
||||
return;
|
||||
case 'notice':
|
||||
|
||||
@@ -18,13 +18,13 @@ class LightCacheInside
|
||||
{
|
||||
try {
|
||||
self::createTable('wait_api', 3, 65536);
|
||||
self::createTable('connect', 3, 64); //用于存单机器人模式下的机器人fd的
|
||||
self::createTable('static_route', 64, 256); //用于存储
|
||||
self::createTable('connect', 3, 64); // 用于存单机器人模式下的机器人fd的
|
||||
self::createTable('static_route', 64, 256); // 用于存储
|
||||
self::createTable('light_array', 8, 512, 0.6);
|
||||
} catch (ZMException $e) {
|
||||
return false;
|
||||
} //用于存协程等待的状态内容的
|
||||
//self::createTable("worker_start", 2, 1024);//用于存启动服务器时的状态的
|
||||
} // 用于存协程等待的状态内容的
|
||||
// self::createTable("worker_start", 2, 1024);//用于存启动服务器时的状态的
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class SpinLock
|
||||
|
||||
public static function lock(string $key)
|
||||
{
|
||||
while (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) { //此资源已经被锁上了
|
||||
while (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) { // 此资源已经被锁上了
|
||||
if (Coroutine::getCid() != -1) {
|
||||
System::sleep(self::$delay / 1000);
|
||||
} else {
|
||||
|
||||
@@ -27,7 +27,7 @@ class CoroutinePool
|
||||
}
|
||||
go(function () use ($func, $name) {
|
||||
self::$cids[$name][] = Coroutine::getCid();
|
||||
//Console::debug("正在执行协程,当前协程池中有 " . count(self::$cids[$name]) . " 个正在运行的协程: ".implode(", ", self::$cids[$name]));
|
||||
// Console::debug("正在执行协程,当前协程池中有 " . count(self::$cids[$name]) . " 个正在运行的协程: ".implode(", ", self::$cids[$name]));
|
||||
$func();
|
||||
self::checkCids($name);
|
||||
});
|
||||
|
||||
45
src/ZM/Utils/Macroable.php
Normal file
45
src/ZM/Utils/Macroable.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
use Closure;
|
||||
use ZM\Exception\MethodNotFoundException;
|
||||
|
||||
trait Macroable
|
||||
{
|
||||
protected static $macros = [];
|
||||
|
||||
public static function __callStatic($method, $parameters)
|
||||
{
|
||||
if (!static::hasMacro($method)) {
|
||||
throw new MethodNotFoundException("Method {$method} does not exist.");
|
||||
}
|
||||
if (static::$macros[$method] instanceof Closure) {
|
||||
return call_user_func_array(Closure::bind(static::$macros[$method], null, static::class), $parameters);
|
||||
}
|
||||
return call_user_func_array(static::$macros[$method], $parameters);
|
||||
}
|
||||
|
||||
public function __call($method, $parameters)
|
||||
{
|
||||
if (!static::hasMacro($method)) {
|
||||
throw new MethodNotFoundException("Method {$method} does not exist.");
|
||||
}
|
||||
if (static::$macros[$method] instanceof Closure) {
|
||||
return call_user_func_array(static::$macros[$method]->bindTo($this, static::class), $parameters);
|
||||
}
|
||||
return call_user_func_array(static::$macros[$method], $parameters);
|
||||
}
|
||||
|
||||
public static function macro($name, callable $macro)
|
||||
{
|
||||
static::$macros[$name] = $macro;
|
||||
}
|
||||
|
||||
public static function hasMacro($name)
|
||||
{
|
||||
return isset(static::$macros[$name]);
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,18 @@ use ZM\Utils\DataProvider;
|
||||
*/
|
||||
class ModuleManager
|
||||
{
|
||||
public static function getComposer()
|
||||
{
|
||||
return json_decode(file_get_contents(DataProvider::getSourceRootDir() . '/composer.json'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描src目录下的所有已经被标注的模块
|
||||
* @throws ZMException
|
||||
*/
|
||||
public static function getConfiguredModules(): array
|
||||
{
|
||||
$composer = self::getComposer();
|
||||
$dir = DataProvider::getSourceRootDir() . '/src/';
|
||||
$ls = DataProvider::scanDirFiles($dir, true, true);
|
||||
$modules = [];
|
||||
@@ -43,7 +49,18 @@ class ModuleManager
|
||||
throw new ZMKnownException('E00052', '在/src/目录下不可以直接标记为模块(zm.json),因为命名空间不能为根空间!');
|
||||
}
|
||||
$json['module-path'] = realpath($dir . '/' . $pathinfo['dirname']);
|
||||
$json['namespace'] = str_replace('/', '\\', $pathinfo['dirname']);
|
||||
|
||||
$relative_path = str_replace(DataProvider::getSourceRootDir() . '/', '', $json['module-path']);
|
||||
foreach (array_merge($composer['autoload']['psr-4'] ?? [], $composer['autoload-dev']['psr-4'] ?? []) as $ks => $vs) {
|
||||
if (strpos($relative_path, $vs) === 0) {
|
||||
$remain = trim(substr($relative_path, strlen($vs)), '/');
|
||||
$remain = str_replace('/', '\\', $remain);
|
||||
$json['namespace'] = $ks . $remain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// $json['namespace'] = str_replace('/', '\\', $pathinfo['dirname']);
|
||||
|
||||
if (isset($modules[$json['name']])) {
|
||||
throw new ZMKnownException('E00053', '重名模块:' . $json['name']);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class RouteManager
|
||||
$route_name = ($tail === '' ? '' : '/') . $tail . '/{filename}';
|
||||
Console::debug('添加静态文件路由:' . $route_name);
|
||||
$route = new Route($route_name, ['_class' => RouteManager::class, '_method' => 'onStaticRoute']);
|
||||
//echo $path.PHP_EOL;
|
||||
// echo $path.PHP_EOL;
|
||||
LightCacheInside::set('static_route', $route->getPath(), $path);
|
||||
|
||||
self::$routes->add(md5($route_name), $route);
|
||||
|
||||
@@ -77,7 +77,7 @@ class SignalListener
|
||||
});
|
||||
self::processKillerPrompt();
|
||||
}
|
||||
//Console::verbose("Interrupted in worker");
|
||||
// Console::verbose("Interrupted in worker");
|
||||
// do nothing
|
||||
});
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class ZMUtil
|
||||
public static function getModInstance($class)
|
||||
{
|
||||
if (!isset(ZMBuf::$instance[$class])) {
|
||||
//Console::debug('Class instance $class not exist, so I created it.');
|
||||
// Console::debug('Class instance $class not exist, so I created it.');
|
||||
return ZMBuf::$instance[$class] = new $class();
|
||||
}
|
||||
return ZMBuf::$instance[$class];
|
||||
@@ -92,7 +92,7 @@ class ZMUtil
|
||||
foreach ($files as $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if (($pathinfo['extension'] ?? '') == 'php') {
|
||||
if ($rule === null) { //规则未设置回调时候,使用默认的识别过滤规则
|
||||
if ($rule === null) { // 规则未设置回调时候,使用默认的识别过滤规则
|
||||
/*if (substr(file_get_contents($dir . '/' . $v), 6, 6) == '#plain') {
|
||||
continue;
|
||||
}*/
|
||||
|
||||
@@ -17,6 +17,7 @@ use ZM\Context\ContextInterface;
|
||||
use ZM\Event\EventManager;
|
||||
use ZM\Exception\RobotNotFoundException;
|
||||
use ZM\Exception\ZMException;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Framework;
|
||||
use ZM\Store\LightCacheInside;
|
||||
use ZM\Store\ZMAtomic;
|
||||
@@ -27,7 +28,7 @@ function getClassPath($class_name)
|
||||
{
|
||||
$dir = str_replace('\\', '/', $class_name);
|
||||
$dir2 = DataProvider::getSourceRootDir() . '/src/' . $dir . '.php';
|
||||
//echo "@@@".$dir2.PHP_EOL;
|
||||
// echo "@@@".$dir2.PHP_EOL;
|
||||
$dir2 = str_replace('\\', '/', $dir2);
|
||||
if (file_exists($dir2)) {
|
||||
return $dir2;
|
||||
@@ -65,7 +66,7 @@ function explodeMsg($msg, $ban_comma = false): array
|
||||
{
|
||||
$msg = str_replace(' ', "\n", trim($msg));
|
||||
if (!$ban_comma) {
|
||||
//$msg = str_replace(",", "\n", $msg);
|
||||
// $msg = str_replace(",", "\n", $msg);
|
||||
$msg = str_replace("\t", "\n", $msg);
|
||||
}
|
||||
$msgs = explode("\n", $msg);
|
||||
@@ -127,7 +128,7 @@ function split_explode($del, $str, $divide_en = false): array
|
||||
}
|
||||
}
|
||||
$str = implode($del, $str);
|
||||
//echo $str."\n";
|
||||
// echo $str."\n";
|
||||
$ls = [];
|
||||
foreach (explode($del, $str) as $v) {
|
||||
if (trim($v) == '') {
|
||||
@@ -135,7 +136,7 @@ function split_explode($del, $str, $divide_en = false): array
|
||||
}
|
||||
$ls[] = $v;
|
||||
}
|
||||
//var_dump($ls);
|
||||
// var_dump($ls);
|
||||
return $ls == [] ? [''] : $ls;
|
||||
}
|
||||
|
||||
@@ -149,7 +150,7 @@ function matchArgs($pattern, $context)
|
||||
$exp = explode('*', $pattern);
|
||||
$i = 0;
|
||||
foreach ($exp as $k => $v) {
|
||||
//echo "[MATCH$k] " . $v . PHP_EOL;
|
||||
// echo "[MATCH$k] " . $v . PHP_EOL;
|
||||
if ($v == '' && $k == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -158,14 +159,14 @@ function matchArgs($pattern, $context)
|
||||
$v = '^EOL';
|
||||
}
|
||||
$cur_var = '';
|
||||
//echo mb_substr($context, $i) . "|" . $v . PHP_EOL;
|
||||
// echo mb_substr($context, $i) . "|" . $v . PHP_EOL;
|
||||
$ori = $i;
|
||||
while (($a = mb_substr($context, $i, mb_strlen($v))) != $v && $a != '') {
|
||||
$cur_var .= mb_substr($context, $i, 1);
|
||||
++$i;
|
||||
}
|
||||
if ($i != $ori || $k == 1 || $k == count($exp) - 1) {
|
||||
//echo $cur_var . PHP_EOL;
|
||||
// echo $cur_var . PHP_EOL;
|
||||
$result[] = $cur_var;
|
||||
}
|
||||
$i += mb_strlen($v);
|
||||
@@ -193,11 +194,11 @@ function connectIs($type): bool
|
||||
function getAnnotations(): array
|
||||
{
|
||||
$s = debug_backtrace()[1];
|
||||
//echo json_encode($s, 128|256);
|
||||
// echo json_encode($s, 128|256);
|
||||
$list = [];
|
||||
foreach (EventManager::$events as $v) {
|
||||
foreach ($v as $vs) {
|
||||
//echo get_class($vs).": ".$vs->class." => ".$vs->method.PHP_EOL;
|
||||
// echo get_class($vs).": ".$vs->class." => ".$vs->method.PHP_EOL;
|
||||
if ($vs->class == $s['class'] && $vs->method == $s['function']) {
|
||||
$list[get_class($vs)][] = $vs;
|
||||
}
|
||||
@@ -224,12 +225,18 @@ function set_coroutine_params($array)
|
||||
}
|
||||
}
|
||||
|
||||
function context(): ?ContextInterface
|
||||
/**
|
||||
* @throws ZMKnownException
|
||||
*/
|
||||
function context(): ContextInterface
|
||||
{
|
||||
return ctx();
|
||||
}
|
||||
|
||||
function ctx(): ?ContextInterface
|
||||
/**
|
||||
* @throws ZMKnownException
|
||||
*/
|
||||
function ctx(): ContextInterface
|
||||
{
|
||||
$cid = Co::getCid();
|
||||
$c_class = ZMConfig::get('global', 'context_class');
|
||||
@@ -243,8 +250,7 @@ function ctx(): ?ContextInterface
|
||||
return ZMBuf::$context_class[$cid] ?? (ZMBuf::$context_class[$cid] = new $c_class($cid));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new ZMKnownException(zm_internal_errcode('E00072') . 'Unable to find context environment');
|
||||
}
|
||||
|
||||
function onebot_target_id_name($message_type): string
|
||||
|
||||
@@ -5,7 +5,10 @@ declare(strict_types=1);
|
||||
function loader__generated_id__()
|
||||
{
|
||||
$obj = json_decode(file_get_contents(__DIR__ . '/zmplugin.json'), true);
|
||||
foreach (($obj['autoload-psr-4'] ?? []) as $v) {
|
||||
foreach (($obj['hotload-psr-4'] ?? []) as $v) {
|
||||
require_once Phar::running() . '/' . $v;
|
||||
}
|
||||
foreach (($obj['hotload-files'] ?? []) as $v) {
|
||||
require_once Phar::running() . '/' . $v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,14 @@ try {
|
||||
$base_path = DataProvider::getSourceRootDir();
|
||||
$scan_paths = [];
|
||||
$composer = json_decode(file_get_contents($base_path . '/composer.json'), true);
|
||||
$exclude_annotations = array_merge($composer['extra']['exclude_annotate'] ?? [], $composer['extra']['zm']['exclude-annotation-path'] ?? []);
|
||||
foreach (($composer['autoload']['psr-4'] ?? []) as $k => $v) {
|
||||
if (is_dir($base_path . '/' . $v) && !in_array($v, $composer['extra']['exclude_annotate'] ?? [])) {
|
||||
if (is_dir($base_path . '/' . $v) && !in_array($v, $exclude_annotations)) {
|
||||
$scan_paths[trim($k, '\\')] = $base_path . '/' . $v;
|
||||
}
|
||||
}
|
||||
foreach (($composer['autoload-dev']['psr-4'] ?? []) as $k => $v) {
|
||||
if (is_dir($base_path . '/' . $v) && !in_array($v, $composer['extra']['exclude_annotate'] ?? [])) {
|
||||
if (is_dir($base_path . '/' . $v) && !in_array($v, $exclude_annotations)) {
|
||||
$scan_paths[trim($k, '\\')] = $base_path . '/' . $v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ class AnnotationParserRegisterTest extends TestCase
|
||||
public function testAnnotation() {
|
||||
ob_start();
|
||||
$gen = $this->parser->generateAnnotationEvents();
|
||||
//zm_dump($gen);
|
||||
$m = $gen[OnStart::class][0]->method;
|
||||
$class = $gen[OnStart::class][0]->class;
|
||||
$c = new $class();
|
||||
@@ -43,12 +44,10 @@ class AnnotationParserRegisterTest extends TestCase
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
$result = ob_get_clean();
|
||||
echo $result;
|
||||
$this->assertStringContainsString("我开始了!", $result);
|
||||
}
|
||||
|
||||
public function testAnnotation2() {
|
||||
|
||||
foreach ($this->parser->generateAnnotationEvents() as $k => $v) {
|
||||
foreach ($v as $vs) {
|
||||
$this->assertTrue($vs->method === null || $vs->method != '');
|
||||
@@ -57,22 +56,9 @@ class AnnotationParserRegisterTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testAnnotationMap() {
|
||||
$map = $this->parser->getMiddlewareMap();
|
||||
$this->assertContainsEquals("timer", $map[Hello::class]["timer"]);
|
||||
}
|
||||
|
||||
public function testMiddlewares() {
|
||||
$wares = $this->parser->getMiddlewares();
|
||||
zm_dump($wares);
|
||||
$this->assertArrayHasKey("timer", $wares);
|
||||
}
|
||||
|
||||
public function testReqMapping() {
|
||||
$mapping = $this->parser->getReqMapping();
|
||||
$this->assertEquals("index", $mapping["method"]);
|
||||
}
|
||||
|
||||
public function testTracer() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user