mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-17 20:54:52 +08:00
Merge pull request #254 from zhamao-robot/plugin-meta-ng
重构插件加载器、BotContext、AnnotationMap 新增方法、修复部分 Bug
This commit is contained in:
commit
b0165e176a
@ -56,8 +56,9 @@ $config['runtime'] = [
|
||||
|
||||
/* 允许加载插件形式 */
|
||||
$config['plugin'] = [
|
||||
'enable' => true,
|
||||
'load_dir' => 'plugins',
|
||||
'enable' => true, // 是否启动插件系统,默认为 true,如果为否则只能使用 src 模式编写用户代码
|
||||
'load_dir' => 'plugins', // 插件目录,相对目录时,代表WORKING_DIR下的目录,绝对目录按照绝对目录来
|
||||
'composer_plugin_enable' => true, // 是否加载 Composer 依赖的插件,如果为 true 则读取 vendor/composer/installed.json 遍历加载
|
||||
];
|
||||
|
||||
/* 内部默认启用的插件 */
|
||||
|
||||
@ -6,135 +6,135 @@
|
||||
|
||||
> 更新时间:2023-01-04
|
||||
|
||||
* 添加 Phar 构建命令 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/226
|
||||
* update v3.sh update script by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/227
|
||||
* 重构命令手册插件 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/228
|
||||
* 重构注解解析器和优化部分代码 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/229
|
||||
* 新增 Redis 支持 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/230
|
||||
* 修复 Route 注解无法正常解析的 Bug by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/231
|
||||
* 添加定时任务支持 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/232
|
||||
* 修复测试结果输出错误 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/233
|
||||
* 暂时停用网络请求测试并修复文件系统测试 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/234
|
||||
* 修复一些小问题和添加 GitAttributes by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/235
|
||||
* 修复 Doxygen 权限 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/238
|
||||
* 更新首页介绍 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/237
|
||||
* 增加 PostgreSQL 支持 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/236
|
||||
* 修复 Doxygen Sudo 权限 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/239
|
||||
* Beta5 系列升级内容(包含 Redis、sendAction 协程、reply 模式、修复 data 报错) by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/240
|
||||
* 重构新的 waitMessage 到 prompt by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/241
|
||||
* 添加 OneBot 12 文件上传和下载工具 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/242
|
||||
* 添加 Phar 构建命令 by [@sunxyw](https://github.com/sunxyw) in [PR#226](https://github.com/zhamao-robot/zhamao-framework/pull/226)
|
||||
* update v3.sh update script by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#227](https://github.com/zhamao-robot/zhamao-framework/pull/227)
|
||||
* 重构命令手册插件 by [@sunxyw](https://github.com/sunxyw) in [PR#228](https://github.com/zhamao-robot/zhamao-framework/pull/228)
|
||||
* 重构注解解析器和优化部分代码 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#229](https://github.com/zhamao-robot/zhamao-framework/pull/229)
|
||||
* 新增 Redis 支持 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#230](https://github.com/zhamao-robot/zhamao-framework/pull/230)
|
||||
* 修复 Route 注解无法正常解析的 Bug by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#231](https://github.com/zhamao-robot/zhamao-framework/pull/231)
|
||||
* 添加定时任务支持 by [@sunxyw](https://github.com/sunxyw) in [PR#232](https://github.com/zhamao-robot/zhamao-framework/pull/232)
|
||||
* 修复测试结果输出错误 by [@sunxyw](https://github.com/sunxyw) in [PR#233](https://github.com/zhamao-robot/zhamao-framework/pull/233)
|
||||
* 暂时停用网络请求测试并修复文件系统测试 by [@sunxyw](https://github.com/sunxyw) in [PR#234](https://github.com/zhamao-robot/zhamao-framework/pull/234)
|
||||
* 修复一些小问题和添加 GitAttributes by [@sunxyw](https://github.com/sunxyw) in [PR#235](https://github.com/zhamao-robot/zhamao-framework/pull/235)
|
||||
* 修复 Doxygen 权限 by [@sunxyw](https://github.com/sunxyw) in [PR#238](https://github.com/zhamao-robot/zhamao-framework/pull/238)
|
||||
* 更新首页介绍 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#237](https://github.com/zhamao-robot/zhamao-framework/pull/237)
|
||||
* 增加 PostgreSQL 支持 by [@sunxyw](https://github.com/sunxyw) in [PR#236](https://github.com/zhamao-robot/zhamao-framework/pull/236)
|
||||
* 修复 Doxygen Sudo 权限 by [@sunxyw](https://github.com/sunxyw) in [PR#239](https://github.com/zhamao-robot/zhamao-framework/pull/239)
|
||||
* Beta5 系列升级内容(包含 Redis、sendAction 协程、reply 模式、修复 data 报错) by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#240](https://github.com/zhamao-robot/zhamao-framework/pull/240)
|
||||
* 重构新的 waitMessage 到 prompt by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#241](https://github.com/zhamao-robot/zhamao-framework/pull/241)
|
||||
* 添加 OneBot 12 文件上传和下载工具 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#242](https://github.com/zhamao-robot/zhamao-framework/pull/242)
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta4...3.0.0-beta5
|
||||
**Full Changelog**: <https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta4...3.0.0-beta5>
|
||||
|
||||
## v3.0.0-beta4
|
||||
|
||||
> 更新时间:2022-12-31
|
||||
|
||||
* 切换 Git Hook 至 Captainhook by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/218
|
||||
* 升级 v3 文档构建发布路径 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/219
|
||||
* 根据最新的分支命名更新 Workflows by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/220
|
||||
* 更新部分文档 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/221
|
||||
* 将 KV 库接口调整为 PSR-16 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/222
|
||||
* 修复有关 BotCommand 的 Bug by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/223
|
||||
* 边缘 Bug 修复 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/224
|
||||
* 重构配置类配置 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/225
|
||||
* 切换 Git Hook 至 Captainhook by [@sunxyw](https://github.com/sunxyw) in [PR#218](https://github.com/zhamao-robot/zhamao-framework/pull/218)
|
||||
* 升级 v3 文档构建发布路径 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#219](https://github.com/zhamao-robot/zhamao-framework/pull/219)
|
||||
* 根据最新的分支命名更新 Workflows by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#220](https://github.com/zhamao-robot/zhamao-framework/pull/220)
|
||||
* 更新部分文档 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#221](https://github.com/zhamao-robot/zhamao-framework/pull/221)
|
||||
* 将 KV 库接口调整为 PSR-16 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#222](https://github.com/zhamao-robot/zhamao-framework/pull/222)
|
||||
* 修复有关 BotCommand 的 Bug by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#223](https://github.com/zhamao-robot/zhamao-framework/pull/223)
|
||||
* 边缘 Bug 修复 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#224](https://github.com/zhamao-robot/zhamao-framework/pull/224)
|
||||
* 重构配置类配置 by [@sunxyw](https://github.com/sunxyw) in [PR#225](https://github.com/zhamao-robot/zhamao-framework/pull/225)
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta3...3.0.0-beta4
|
||||
**Full Changelog**: <https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta3...3.0.0-beta4>
|
||||
|
||||
## v3.0.0-beta3
|
||||
|
||||
> 更新时间:2022-12-31
|
||||
|
||||
* 添加 Windows 入口 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/208
|
||||
* 重构异常处理 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/209
|
||||
* 添加命令帮助插件 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/210
|
||||
* 加(一些)事件文档 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/212
|
||||
* 修复 BotContext 不同步问题 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/211
|
||||
* 让容器支持协程 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/213
|
||||
* 拆分 Bot 动作到 Trait 以及更新一些类型强化的代码 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/214
|
||||
* 添加 v3 版本的一键安装脚本 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/215
|
||||
* 新增 ZMRequest by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/216
|
||||
* 新增全新的 LightCache by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/217
|
||||
* 添加 Windows 入口 by [@sunxyw](https://github.com/sunxyw) in [PR#208](https://github.com/zhamao-robot/zhamao-framework/pull/208)
|
||||
* 重构异常处理 by [@sunxyw](https://github.com/sunxyw) in [PR#209](https://github.com/zhamao-robot/zhamao-framework/pull/209)
|
||||
* 添加命令帮助插件 by [@sunxyw](https://github.com/sunxyw) in [PR#210](https://github.com/zhamao-robot/zhamao-framework/pull/210)
|
||||
* 加(一些)事件文档 by [@sunxyw](https://github.com/sunxyw) in [PR#212](https://github.com/zhamao-robot/zhamao-framework/pull/212)
|
||||
* 修复 BotContext 不同步问题 by [@sunxyw](https://github.com/sunxyw) in [PR#211](https://github.com/zhamao-robot/zhamao-framework/pull/211)
|
||||
* 让容器支持协程 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#213](https://github.com/zhamao-robot/zhamao-framework/pull/213)
|
||||
* 拆分 Bot 动作到 Trait 以及更新一些类型强化的代码 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#214](https://github.com/zhamao-robot/zhamao-framework/pull/214)
|
||||
* 添加 v3 版本的一键安装脚本 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#215](https://github.com/zhamao-robot/zhamao-framework/pull/215)
|
||||
* 新增 ZMRequest by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#216](https://github.com/zhamao-robot/zhamao-framework/pull/216)
|
||||
* 新增全新的 LightCache by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#217](https://github.com/zhamao-robot/zhamao-framework/pull/217)
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta2...3.0.0-beta3
|
||||
**Full Changelog**: <https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta2...3.0.0-beta3>
|
||||
|
||||
## v3.0.0-beta2
|
||||
|
||||
> 更新时间:2022-12-26
|
||||
|
||||
* 修复相对路径问题 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/190
|
||||
* 改进测试运行 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/193
|
||||
* 添加些许测试 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/194
|
||||
* 添加 EventProvider 测试 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/195
|
||||
* 修复 getClassesPsr4 中默认过滤方法的路径 Bug by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/198
|
||||
* 用 Doxygen 替代 API Docs by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/192
|
||||
* 重构配置类测试 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/199
|
||||
* 新增 CatCode encode 时选择是否编码文本的参数 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/197
|
||||
* 切换容器实现为 PHP-DI by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/201
|
||||
* 添加 HttpEventListener 测试 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/200
|
||||
* 添加插件生成功能 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/202
|
||||
* 完善 BotCommand 和 CommandArgument 的解析 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/203
|
||||
* 重写文档 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/205
|
||||
* 发布 beta2 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/206
|
||||
* 修复相对路径问题 by [@sunxyw](https://github.com/sunxyw) in [PR#190](https://github.com/zhamao-robot/zhamao-framework/pull/190)
|
||||
* 改进测试运行 by [@sunxyw](https://github.com/sunxyw) in [PR#193](https://github.com/zhamao-robot/zhamao-framework/pull/193)
|
||||
* 添加些许测试 by [@sunxyw](https://github.com/sunxyw) in [PR#194](https://github.com/zhamao-robot/zhamao-framework/pull/194)
|
||||
* 添加 EventProvider 测试 by [@sunxyw](https://github.com/sunxyw) in [PR#195](https://github.com/zhamao-robot/zhamao-framework/pull/195)
|
||||
* 修复 getClassesPsr4 中默认过滤方法的路径 Bug by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#198](https://github.com/zhamao-robot/zhamao-framework/pull/198)
|
||||
* 用 Doxygen 替代 API Docs by [@sunxyw](https://github.com/sunxyw) in [PR#192](https://github.com/zhamao-robot/zhamao-framework/pull/192)
|
||||
* 重构配置类测试 by [@sunxyw](https://github.com/sunxyw) in [PR#199](https://github.com/zhamao-robot/zhamao-framework/pull/199)
|
||||
* 新增 CatCode encode 时选择是否编码文本的参数 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#197](https://github.com/zhamao-robot/zhamao-framework/pull/197)
|
||||
* 切换容器实现为 PHP-DI by [@sunxyw](https://github.com/sunxyw) in [PR#201](https://github.com/zhamao-robot/zhamao-framework/pull/201)
|
||||
* 添加 HttpEventListener 测试 by [@sunxyw](https://github.com/sunxyw) in [PR#200](https://github.com/zhamao-robot/zhamao-framework/pull/200)
|
||||
* 添加插件生成功能 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#202](https://github.com/zhamao-robot/zhamao-framework/pull/202)
|
||||
* 完善 BotCommand 和 CommandArgument 的解析 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#203](https://github.com/zhamao-robot/zhamao-framework/pull/203)
|
||||
* 重写文档 by [@sunxyw](https://github.com/sunxyw) in [PR#205](https://github.com/zhamao-robot/zhamao-framework/pull/205)
|
||||
* 发布 beta2 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#206](https://github.com/zhamao-robot/zhamao-framework/pull/206)
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta1...3.0.0-beta2
|
||||
**Full Changelog**: <https://github.com/zhamao-robot/zhamao-framework/compare/3.0.0-beta1...3.0.0-beta2>
|
||||
|
||||
## v3.0.0-beta1
|
||||
|
||||
> 更新时间:2022-12-20
|
||||
|
||||
* 修改 Workflows 以适配未来开发 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/123
|
||||
* 添加 Adapter 基础 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/121
|
||||
* 重构 ZMConfig by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/124
|
||||
* 框架V3部分重构 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/125
|
||||
* 添加 PHPStan 相关扩展 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/126
|
||||
* 添加日志配置 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/127
|
||||
* 移除废弃的全局函数 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/130
|
||||
* 轻量重构 Framework 类 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/131
|
||||
* 优化容器服务注册 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/129
|
||||
* 修复 OneBot11Adapter 无限回调溢出及其他小补丁 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/133
|
||||
* 替换 zhamao/console 为 zhamao/logger by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/135
|
||||
* 3.0 重构驱动 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/138
|
||||
* fix container and coroutine bug by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/144
|
||||
* Refactor/phpunit test rebuild by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/147
|
||||
* 完善 MySQL 连接池和组件 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/148
|
||||
* 修复 gendoc 不兼容 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/150
|
||||
* 添加类别名 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/149
|
||||
* 修复对 Windows 环境开发的支持 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/151
|
||||
* add phpunit windows support by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/152
|
||||
* 基于 LibOB Config 类重构 ZMConfig by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/146
|
||||
* 添加 REPL (PsySH) 集成 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/155
|
||||
* 修正&改进配置加载 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/157
|
||||
* Sqlite 支持 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/160
|
||||
* 修复 Framework 中 Config 重写的 Bug by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/161
|
||||
* FileSystem.php isRelativePath() 对 Windows 的兼容性 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/162
|
||||
* 添加日志追踪功能 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/159
|
||||
* 添加定制PHPUnit样式 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/164
|
||||
* 取消配置ArrayAccess支持 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/163
|
||||
* 重构 Workflow by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/165
|
||||
* 修复 isRelativePath 在 Windows 环境判断相反的 Bug by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/167
|
||||
* 修复上游 Config 类更改 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/168
|
||||
* add state and ctrl+C support for windows by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/169
|
||||
* 更新Workflow by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/171
|
||||
* 添加代理、升级到 PHP8.0 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/170
|
||||
* 重新组织 Bootstraper by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/172
|
||||
* 改进异常 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/173
|
||||
* 增加 Docker Compose 支持 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/176
|
||||
* 添加贡献指南 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/178
|
||||
* 迁移 Symfony Console V6 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/179
|
||||
* 兼容 8.x PHP 一些改动 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/181
|
||||
* 升级部分依赖 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/180
|
||||
* 插件和 OneBot 12 适配器前置内容 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/184
|
||||
* 完善插件加载系统 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/185
|
||||
* 更新 README 测试徽章路径 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/186
|
||||
* PHP80 小修 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/187
|
||||
* 容器增加 class_alias 支持 by @sunxyw in https://github.com/zhamao-robot/zhamao-framework/pull/189
|
||||
* Beta 1 发布 by @crazywhalecc in https://github.com/zhamao-robot/zhamao-framework/pull/188
|
||||
* 修改 Workflows 以适配未来开发 by [@sunxyw](https://github.com/sunxyw) in [PR#123](https://github.com/zhamao-robot/zhamao-framework/pull/123)
|
||||
* 添加 Adapter 基础 by [@sunxyw](https://github.com/sunxyw) in [PR#121](https://github.com/zhamao-robot/zhamao-framework/pull/121)
|
||||
* 重构 ZMConfig by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#124](https://github.com/zhamao-robot/zhamao-framework/pull/124)
|
||||
* 框架V3部分重构 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#125](https://github.com/zhamao-robot/zhamao-framework/pull/125)
|
||||
* 添加 PHPStan 相关扩展 by [@sunxyw](https://github.com/sunxyw) in [PR#126](https://github.com/zhamao-robot/zhamao-framework/pull/126)
|
||||
* 添加日志配置 by [@sunxyw](https://github.com/sunxyw) in [PR#127](https://github.com/zhamao-robot/zhamao-framework/pull/127)
|
||||
* 移除废弃的全局函数 by [@sunxyw](https://github.com/sunxyw) in [PR#130](https://github.com/zhamao-robot/zhamao-framework/pull/130)
|
||||
* 轻量重构 Framework 类 by [@sunxyw](https://github.com/sunxyw) in [PR#131](https://github.com/zhamao-robot/zhamao-framework/pull/131)
|
||||
* 优化容器服务注册 by [@sunxyw](https://github.com/sunxyw) in [PR#129](https://github.com/zhamao-robot/zhamao-framework/pull/129)
|
||||
* 修复 OneBot11Adapter 无限回调溢出及其他小补丁 by [@sunxyw](https://github.com/sunxyw) in [PR#133](https://github.com/zhamao-robot/zhamao-framework/pull/133)
|
||||
* 替换 zhamao/console 为 zhamao/logger by [@sunxyw](https://github.com/sunxyw) in [PR#135](https://github.com/zhamao-robot/zhamao-framework/pull/135)
|
||||
* 3.0 重构驱动 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#138](https://github.com/zhamao-robot/zhamao-framework/pull/138)
|
||||
* fix container and coroutine bug by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#144](https://github.com/zhamao-robot/zhamao-framework/pull/144)
|
||||
* Refactor/phpunit test rebuild by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#147](https://github.com/zhamao-robot/zhamao-framework/pull/147)
|
||||
* 完善 MySQL 连接池和组件 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#148](https://github.com/zhamao-robot/zhamao-framework/pull/148)
|
||||
* 修复 gendoc 不兼容 by [@sunxyw](https://github.com/sunxyw) in [PR#150](https://github.com/zhamao-robot/zhamao-framework/pull/150)
|
||||
* 添加类别名 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#149](https://github.com/zhamao-robot/zhamao-framework/pull/149)
|
||||
* 修复对 Windows 环境开发的支持 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#151](https://github.com/zhamao-robot/zhamao-framework/pull/151)
|
||||
* add phpunit windows support by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#152](https://github.com/zhamao-robot/zhamao-framework/pull/152)
|
||||
* 基于 LibOB Config 类重构 ZMConfig by [@sunxyw](https://github.com/sunxyw) in [PR#146](https://github.com/zhamao-robot/zhamao-framework/pull/146)
|
||||
* 添加 REPL (PsySH) 集成 by [@sunxyw](https://github.com/sunxyw) in [PR#155](https://github.com/zhamao-robot/zhamao-framework/pull/155)
|
||||
* 修正&改进配置加载 by [@sunxyw](https://github.com/sunxyw) in [PR#157](https://github.com/zhamao-robot/zhamao-framework/pull/157)
|
||||
* Sqlite 支持 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#160](https://github.com/zhamao-robot/zhamao-framework/pull/160)
|
||||
* 修复 Framework 中 Config 重写的 Bug by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#161](https://github.com/zhamao-robot/zhamao-framework/pull/161)
|
||||
* FileSystem.php isRelativePath() 对 Windows 的兼容性 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#162](https://github.com/zhamao-robot/zhamao-framework/pull/162)
|
||||
* 添加日志追踪功能 by [@sunxyw](https://github.com/sunxyw) in [PR#159](https://github.com/zhamao-robot/zhamao-framework/pull/159)
|
||||
* 添加定制PHPUnit样式 by [@sunxyw](https://github.com/sunxyw) in [PR#164](https://github.com/zhamao-robot/zhamao-framework/pull/164)
|
||||
* 取消配置ArrayAccess支持 by [@sunxyw](https://github.com/sunxyw) in [PR#163](https://github.com/zhamao-robot/zhamao-framework/pull/163)
|
||||
* 重构 Workflow by [@sunxyw](https://github.com/sunxyw) in [PR#165](https://github.com/zhamao-robot/zhamao-framework/pull/165)
|
||||
* 修复 isRelativePath 在 Windows 环境判断相反的 Bug by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#167](https://github.com/zhamao-robot/zhamao-framework/pull/167)
|
||||
* 修复上游 Config 类更改 by [@sunxyw](https://github.com/sunxyw) in [PR#168](https://github.com/zhamao-robot/zhamao-framework/pull/168)
|
||||
* add state and ctrl+C support for windows by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#169](https://github.com/zhamao-robot/zhamao-framework/pull/169)
|
||||
* 更新Workflow by [@sunxyw](https://github.com/sunxyw) in [PR#171](https://github.com/zhamao-robot/zhamao-framework/pull/171)
|
||||
* 添加代理、升级到 PHP8.0 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#170](https://github.com/zhamao-robot/zhamao-framework/pull/170)
|
||||
* 重新组织 Bootstraper by [@sunxyw](https://github.com/sunxyw) in [PR#172](https://github.com/zhamao-robot/zhamao-framework/pull/172)
|
||||
* 改进异常 by [@sunxyw](https://github.com/sunxyw) in [PR#173](https://github.com/zhamao-robot/zhamao-framework/pull/173)
|
||||
* 增加 Docker Compose 支持 by [@sunxyw](https://github.com/sunxyw) in [PR#176](https://github.com/zhamao-robot/zhamao-framework/pull/176)
|
||||
* 添加贡献指南 by [@sunxyw](https://github.com/sunxyw) in [PR#178](https://github.com/zhamao-robot/zhamao-framework/pull/178)
|
||||
* 迁移 Symfony Console V6 by [@sunxyw](https://github.com/sunxyw) in [PR#179](https://github.com/zhamao-robot/zhamao-framework/pull/179)
|
||||
* 兼容 8.x PHP 一些改动 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#181](https://github.com/zhamao-robot/zhamao-framework/pull/181)
|
||||
* 升级部分依赖 by [@sunxyw](https://github.com/sunxyw) in [PR#180](https://github.com/zhamao-robot/zhamao-framework/pull/180)
|
||||
* 插件和 OneBot 12 适配器前置内容 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#184](https://github.com/zhamao-robot/zhamao-framework/pull/184)
|
||||
* 完善插件加载系统 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#185](https://github.com/zhamao-robot/zhamao-framework/pull/185)
|
||||
* 更新 README 测试徽章路径 by [@sunxyw](https://github.com/sunxyw) in [PR#186](https://github.com/zhamao-robot/zhamao-framework/pull/186)
|
||||
* PHP80 小修 by [@sunxyw](https://github.com/sunxyw) in [PR#187](https://github.com/zhamao-robot/zhamao-framework/pull/187)
|
||||
* 容器增加 class_alias 支持 by [@sunxyw](https://github.com/sunxyw) in [PR#189](https://github.com/zhamao-robot/zhamao-framework/pull/189)
|
||||
* Beta 1 发布 by [@crazywhalecc](https://github.com/crazywhalecc) in [PR#188](https://github.com/zhamao-robot/zhamao-framework/pull/188)
|
||||
|
||||
|
||||
**Full Changelog**: https://github.com/zhamao-robot/zhamao-framework/compare/2.8.0...3.0.0-beta1
|
||||
**Full Changelog**: <https://github.com/zhamao-robot/zhamao-framework/compare/2.8.0...3.0.0-beta1>
|
||||
|
||||
|
||||
@ -43,6 +43,11 @@ const ZM_PROMPT_TIMEOUT_MENTION_USER = 4; // 回复超时时 at 该用户
|
||||
const ZM_PROMPT_TIMEOUT_QUOTE_SELF = 8; // 回复超时时引用自己回复的提示语句
|
||||
const ZM_PROMPT_TIMEOUT_QUOTE_USER = 16; // 回复超时时引用用户的消息
|
||||
|
||||
const ZM_PLUGIN_TYPE_NATIVE = 0; // 原生类型的插件,特指内部插件、ZMApplication 继承的插件
|
||||
const ZM_PLUGIN_TYPE_PHAR = 1; // Phar 类型的插件
|
||||
const ZM_PLUGIN_TYPE_SOURCE = 2; // 源码类型的插件
|
||||
const ZM_PLUGIN_TYPE_COMPOSER = 3; // Composer 依赖的插件
|
||||
|
||||
const LOAD_MODE_VENDOR = 0; // 从 vendor 加载
|
||||
const LOAD_MODE_SRC = 1; // 从 src 加载
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ use OneBot\Driver\Coroutine\CoroutineInterface;
|
||||
use OneBot\Driver\Process\ExecutionResult;
|
||||
use OneBot\V12\Object\MessageSegment;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use ZM\Config\Environment;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Container\ContainerHolder;
|
||||
@ -260,6 +261,12 @@ function bot(): ZM\Context\BotContext
|
||||
return new \ZM\Context\BotContext('', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个 KV 库实例
|
||||
*
|
||||
* @param string $name KV 库名称
|
||||
* @return CacheInterface
|
||||
*/
|
||||
function kv(string $name = ''): Psr\SimpleCache\CacheInterface
|
||||
{
|
||||
global $kv_class;
|
||||
|
||||
@ -33,7 +33,7 @@ function _zm_setup_loader()
|
||||
return true;
|
||||
});
|
||||
|
||||
// TODO: 然后加载插件目录下的插件
|
||||
// 这里好像没必要加载插件目录的插件,插件理论上不能在 Master 被加载
|
||||
|
||||
// 解析所有注册路径的文件,获取注解
|
||||
$parser->parse();
|
||||
|
||||
@ -37,6 +37,24 @@ class AnnotationMap
|
||||
self::$_map = array_merge_recursive(self::$_map, $map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个独立的注解到全局注解列表中
|
||||
*
|
||||
* @param AnnotationBase $annotation 注解对象
|
||||
* @param bool $sort 是否在添加后排序(默认为 False)
|
||||
*/
|
||||
public static function addSingleAnnotation(AnnotationBase $annotation, bool $sort = false): void
|
||||
{
|
||||
self::$_list[get_class($annotation)][] = $annotation;
|
||||
if ($annotation->class !== '') {
|
||||
self::$_map[$annotation->class][$annotation->method][] = $annotation;
|
||||
}
|
||||
|
||||
if ($sort) {
|
||||
self::sortAnnotationList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AnnotationBase[]
|
||||
*/
|
||||
@ -46,7 +64,7 @@ class AnnotationMap
|
||||
}
|
||||
|
||||
/**
|
||||
* 排序所有的注解
|
||||
* 排序所有的注解(仅排序 List,不排序 Map)
|
||||
*/
|
||||
public static function sortAnnotationList(): void
|
||||
{
|
||||
|
||||
@ -31,4 +31,9 @@ class Cron extends AnnotationBase
|
||||
) {
|
||||
$this->expression = new CronExpression($expression);
|
||||
}
|
||||
|
||||
public static function make(string $expression, int $worker_id = 0, bool $no_overlap = false): Cron
|
||||
{
|
||||
return new Cron($expression, $worker_id, $no_overlap);
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,13 @@ class BotAction extends AnnotationBase implements Level
|
||||
{
|
||||
}
|
||||
|
||||
public static function make(callable $callback, string $action, bool $need_response = false, int $level = 20): BotAction
|
||||
{
|
||||
$action = new BotAction($action, $need_response, $level);
|
||||
$action->on($callback);
|
||||
return $action;
|
||||
}
|
||||
|
||||
public function getLevel()
|
||||
{
|
||||
return $this->level;
|
||||
|
||||
@ -71,6 +71,16 @@ class TextGenerateCommand extends Command
|
||||
$line .= '## v' . $v['tag_name'] . "\r\n\r\n" . $time . "\r\n\r\n" . trim(str_replace("## What's Changed", '', $v['body'])) . "\r\n\r\n";
|
||||
}
|
||||
$line = str_replace("\r\n", "\n", $line);
|
||||
|
||||
// 将所有的链接转换为可点击的链接,例如 https://example.com -> <https://example.com>
|
||||
$line = preg_replace('/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&\/=]*)/', '<$0>', $line);
|
||||
|
||||
// 替换 PR 链接,例如 <.../pull/123> -> [PR#123](.../pull/123)
|
||||
$line = preg_replace('/<(https:\/\/github\.com\S+zhamao-framework\/pull\/(\d+))>/', '[PR#$2]($1)', $line);
|
||||
|
||||
// 将 mention 转换为可点击的链接,例如 @sunxyw -> [@sunxyw](https://github.com/sunxyw)
|
||||
$line = preg_replace('/(?<=^|\s)@([\w.]+)(?<!\.)/', '[@$1](https://github.com/$1)', $line);
|
||||
|
||||
file_put_contents(FRAMEWORK_ROOT_DIR . '/docs/update/v3.md', $line);
|
||||
return static::SUCCESS;
|
||||
}
|
||||
|
||||
41
src/ZM/Command/Plugin/PluginPackCommand.php
Normal file
41
src/ZM/Command/Plugin/PluginPackCommand.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Command\Plugin;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use ZM\Bootstrap;
|
||||
use ZM\Command\Command;
|
||||
use ZM\Exception\PluginException;
|
||||
use ZM\Plugin\PluginManager;
|
||||
|
||||
#[AsCommand(name: 'plugin:pack', description: '打包插件到 Phar 格式')]
|
||||
class PluginPackCommand extends Command
|
||||
{
|
||||
protected array $bootstrappers = [
|
||||
BootStrap\RegisterLogger::class,
|
||||
Bootstrap\SetInternalTimezone::class,
|
||||
Bootstrap\LoadConfiguration::class,
|
||||
];
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->addArgument('name', InputArgument::REQUIRED, '要打包的插件名称');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function handle(): int
|
||||
{
|
||||
try {
|
||||
PluginManager::packPlugin($this->input->getArgument('name'));
|
||||
} catch (PluginException $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
$this->output->writeln('打包插件到 Phar 格式');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -19,7 +19,7 @@ class ContainerRegistrant
|
||||
/**
|
||||
* 应在收到 OneBot 事件时调用
|
||||
*/
|
||||
public static function registerOBEventServices(OneBotEvent $event): void
|
||||
public static function registerOBEventServices(OneBotEvent $event, string $bot_context = BotContext::class): void
|
||||
{
|
||||
self::addServices([
|
||||
OneBotEvent::class => $event,
|
||||
@ -28,7 +28,7 @@ class ContainerRegistrant
|
||||
|
||||
if (isset($event->self['platform'])) {
|
||||
self::addServices([
|
||||
BotContext::class => DI\autowire(BotContext::class)->constructor(
|
||||
BotContext::class => DI\autowire($bot_context)->constructor(
|
||||
$event->self['user_id'] ?? '',
|
||||
$event->self['platform'],
|
||||
),
|
||||
|
||||
@ -22,9 +22,9 @@ trait BotActionTrait
|
||||
/**
|
||||
* @var array<string, int> 一个记录 echo 对应协程 ID 的列表,用于恢复协程
|
||||
*/
|
||||
private static array $coroutine_list = [];
|
||||
protected static array $coroutine_list = [];
|
||||
|
||||
private null|WebSocketMessageEvent|HttpRequestEvent $base_event;
|
||||
protected null|WebSocketMessageEvent|HttpRequestEvent $base_event;
|
||||
|
||||
/**
|
||||
* @internal 只允许内部调用
|
||||
@ -32,8 +32,8 @@ trait BotActionTrait
|
||||
*/
|
||||
public static function tryResume(ActionResponse $response): void
|
||||
{
|
||||
if (($co = Adaptive::getCoroutine()) !== null && isset(self::$coroutine_list[$response->echo ?? ''])) {
|
||||
$co->resume(self::$coroutine_list[$response->echo ?? ''], $response);
|
||||
if (($co = Adaptive::getCoroutine()) !== null && isset(static::$coroutine_list[$response->echo ?? ''])) {
|
||||
$co->resume(static::$coroutine_list[$response->echo ?? ''], $response);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ trait BotActionTrait
|
||||
}
|
||||
// 如果开启了协程,并且成功发送,那就进入协程等待,挂起等待结果返回一个 ActionResponse 对象
|
||||
if (($result ?? false) === true && ($co = Adaptive::getCoroutine()) !== null) {
|
||||
self::$coroutine_list[$a->echo] = $co->getCid();
|
||||
static::$coroutine_list[$a->echo] = $co->getCid();
|
||||
$response = $co->suspend();
|
||||
if ($response instanceof ActionResponse) {
|
||||
return $response;
|
||||
|
||||
@ -12,16 +12,19 @@ use ZM\Annotation\AnnotationHandler;
|
||||
use ZM\Annotation\AnnotationMap;
|
||||
use ZM\Annotation\AnnotationParser;
|
||||
use ZM\Annotation\Framework\Init;
|
||||
use ZM\Exception\PluginException;
|
||||
use ZM\Exception\ZMKnownException;
|
||||
use ZM\Framework;
|
||||
use ZM\Plugin\CommandManual\CommandManualPlugin;
|
||||
use ZM\Plugin\OneBot12Adapter;
|
||||
use ZM\Plugin\PluginManager;
|
||||
use ZM\Plugin\PluginMeta;
|
||||
use ZM\Process\ProcessStateManager;
|
||||
use ZM\Store\Database\DBException;
|
||||
use ZM\Store\Database\DBPool;
|
||||
use ZM\Store\FileSystem;
|
||||
use ZM\Store\KV\LightCache;
|
||||
use ZM\Store\KV\Redis\RedisException;
|
||||
use ZM\Store\KV\Redis\RedisPool;
|
||||
use ZM\Utils\ZMUtil;
|
||||
|
||||
@ -104,6 +107,10 @@ class WorkerEventListener
|
||||
} else {
|
||||
$this->dispatchInit();
|
||||
}
|
||||
// Windows 系统的 CtrlC 由于和 Select 有一定的冲突,如果没事件解析的话 CtrlC 会阻塞,所以必须添加一个空的计时器
|
||||
if (PHP_OS_FAMILY === 'Windows') {
|
||||
Framework::getInstance()->getDriver()->getEventLoop()->addTimer(1000, function () {}, 0);
|
||||
}
|
||||
// 回显 debug 日志:进程占用的内存
|
||||
$memory_total = memory_get_usage() / 1024 / 1024;
|
||||
logger()->debug('Worker process used ' . round($memory_total, 3) . ' MB');
|
||||
@ -167,11 +174,15 @@ class WorkerEventListener
|
||||
if (!$enable) {
|
||||
continue;
|
||||
}
|
||||
match ($name) {
|
||||
'onebot12' => PluginManager::addPlugin(['name' => $name, 'version' => '1.0', 'internal' => true, 'object' => new OneBot12Adapter(parser: $parser)]),
|
||||
'onebot12-ban-other-ws' => PluginManager::addPlugin(['name' => $name, 'version' => '1.0', 'internal' => true, 'object' => new OneBot12Adapter(submodule: $name)]),
|
||||
'command-manual' => PluginManager::addPlugin(['name' => $name, 'version' => '1.0', 'internal' => true, 'object' => new CommandManualPlugin($parser)]),
|
||||
$plugin = match ($name) {
|
||||
'onebot12' => new OneBot12Adapter(parser: $parser),
|
||||
'onebot12-ban-other-ws' => new OneBot12Adapter(submodule: $name),
|
||||
'command-manual' => new CommandManualPlugin($parser),
|
||||
default => throw new PluginException('Unknown native plugin: ' . $name),
|
||||
};
|
||||
$meta = new PluginMeta(['name' => $name], ZM_PLUGIN_TYPE_NATIVE);
|
||||
$meta->bindEntity($plugin);
|
||||
PluginManager::addPlugin($meta);
|
||||
}
|
||||
|
||||
// 然后加载插件目录的插件
|
||||
@ -184,8 +195,19 @@ class WorkerEventListener
|
||||
}
|
||||
$load_dir = zm_dir($load_dir);
|
||||
|
||||
// 从 plugins 目录加载插件,包含 phar 和文件夹形式
|
||||
$count = PluginManager::addPluginsFromDir($load_dir);
|
||||
logger()->info('Loaded ' . $count . ' user plugins');
|
||||
if ($count !== 0) {
|
||||
logger()->info('Loaded ' . $count . ' user plugins from plugin dir');
|
||||
}
|
||||
|
||||
// 从 composer 依赖加载插件
|
||||
if (config('global.plugin.composer_plugin_enable', true)) {
|
||||
$count = PluginManager::addPluginsFromComposer();
|
||||
if ($count !== 0) {
|
||||
logger()->info('Loaded ' . $count . ' user plugins from composer');
|
||||
}
|
||||
}
|
||||
|
||||
// 启用并初始化插件
|
||||
PluginManager::enablePlugins($parser);
|
||||
@ -215,9 +237,7 @@ class WorkerEventListener
|
||||
/**
|
||||
* 初始化各种连接池
|
||||
*
|
||||
* TODO:未来新增其他db的连接池
|
||||
*
|
||||
* @throws DBException
|
||||
* @throws DBException|RedisException
|
||||
*/
|
||||
private function initConnectionPool(): void
|
||||
{
|
||||
@ -225,11 +245,12 @@ class WorkerEventListener
|
||||
foreach (DBPool::getAllPools() as $name => $pool) {
|
||||
DBPool::destroyPool($name);
|
||||
}
|
||||
// 清空 Redis 连接池
|
||||
foreach (RedisPool::getAllPools() as $name => $pool) {
|
||||
RedisPool::destroyPool($name);
|
||||
}
|
||||
|
||||
// 读取 MySQL 配置文件
|
||||
// 读取 MySQL/PostgresSQL/SQLite 配置文件并创建连接池
|
||||
$conf = config('global.database');
|
||||
// 如果有多个数据库连接,则遍历
|
||||
foreach ($conf as $name => $conn_conf) {
|
||||
@ -238,6 +259,7 @@ class WorkerEventListener
|
||||
}
|
||||
}
|
||||
|
||||
// 读取 Redis 配置文件并创建池
|
||||
$redis_conf = config('global.redis');
|
||||
foreach ($redis_conf as $name => $conn_conf) {
|
||||
if (($conn_conf['enable'] ?? true) !== false) {
|
||||
|
||||
@ -51,8 +51,6 @@ class CommandManualPlugin extends ZMPlugin
|
||||
|
||||
public function __construct(AnnotationParser $parser)
|
||||
{
|
||||
parent::__construct(__DIR__);
|
||||
|
||||
if (config('command_manual.template') !== null) {
|
||||
$this->template = config('command_manual.template');
|
||||
}
|
||||
|
||||
@ -51,7 +51,6 @@ class OneBot12Adapter extends ZMPlugin
|
||||
|
||||
public function __construct(string $submodule = '', ?AnnotationParser $parser = null)
|
||||
{
|
||||
parent::__construct(__DIR__);
|
||||
switch ($submodule) {
|
||||
case '':
|
||||
case 'onebot12':
|
||||
@ -256,7 +255,8 @@ class OneBot12Adapter extends ZMPlugin
|
||||
{
|
||||
// 判断是不是 OneBot 12 反向 WS 连进来的,通过 Sec-WebSocket-Protocol 头
|
||||
$line = explode('.', $event->getRequest()->getHeaderLine('Sec-WebSocket-Protocol'), 2);
|
||||
if ($line[0] !== '12') {
|
||||
// 如果不是 12 并且在这个最低等级事件之前还没有设置了连接信息的,一律干掉
|
||||
if (empty(ConnectionUtil::getConnection($event->getFd())) && $line[0] !== '12') {
|
||||
logger()->warning('不允许接入除 OneBot 12 以外的 WebSocket Client');
|
||||
$event->withResponse(HttpFactory::createResponse(403, 'Forbidden'));
|
||||
$event->stopPropagation();
|
||||
|
||||
@ -8,31 +8,12 @@ use Jelix\Version\VersionComparator;
|
||||
use ZM\Annotation\AnnotationMap;
|
||||
use ZM\Annotation\AnnotationParser;
|
||||
use ZM\Annotation\Framework\BindEvent;
|
||||
use ZM\Annotation\OneBot\BotCommand;
|
||||
use ZM\Annotation\OneBot\BotEvent;
|
||||
use ZM\Exception\PluginException;
|
||||
use ZM\Store\FileSystem;
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
private const DEFAULT_META = [
|
||||
'name' => '<anonymous>',
|
||||
'version' => 'dev',
|
||||
'dir' => '',
|
||||
'object' => null,
|
||||
'entry_file' => null,
|
||||
'autoload' => null,
|
||||
'dependencies' => [],
|
||||
];
|
||||
|
||||
/** @var array|string[] 缺省的自动加载插件的入口文件 */
|
||||
public static array $default_entries = [
|
||||
'main.php',
|
||||
'entry.php',
|
||||
'index.php',
|
||||
];
|
||||
|
||||
/** @var array 插件信息列表 */
|
||||
/** @var array<string, PluginMeta> 插件信息列表 */
|
||||
private static array $plugins = [];
|
||||
|
||||
/**
|
||||
@ -51,117 +32,158 @@ class PluginManager
|
||||
$list = FileSystem::scanDirFiles($dir, false, false, true);
|
||||
$cnt = 0;
|
||||
foreach ($list as $item) {
|
||||
// 检查是不是 phar 格式的插件
|
||||
if (is_file($item) && pathinfo($item, PATHINFO_EXTENSION) === 'phar') {
|
||||
// 如果是PHP文件,尝试添加插件
|
||||
self::addPluginFromPhar($item);
|
||||
++$cnt;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 必须是目录形式的插件
|
||||
if (!is_dir($item)) {
|
||||
continue;
|
||||
}
|
||||
$plugin_meta = self::DEFAULT_META;
|
||||
$plugin_meta['dir'] = $item;
|
||||
|
||||
// 看看有没有插件信息文件
|
||||
$info_file = $item . '/zmplugin.json';
|
||||
$main_file = '';
|
||||
// 如果有的话,就从插件信息文件中找到插件信息
|
||||
if (is_file($info_file)) {
|
||||
$info = json_decode(file_get_contents($info_file), true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
logger()->error('插件信息文件解析失败: ' . json_last_error_msg());
|
||||
continue;
|
||||
}
|
||||
// 设置名称(如果有)
|
||||
$plugin_meta['name'] = $info['name'] ?? ('<anonymous:' . pathinfo($item, PATHINFO_BASENAME) . '>');
|
||||
// 设置版本(如果有)
|
||||
if (isset($info['version'])) {
|
||||
$plugin_meta['version'] = $info['version'];
|
||||
}
|
||||
// 设置了入口文件,则遵循这个入口文件
|
||||
if (isset($info['main'])) {
|
||||
$main_file = FileSystem::isRelativePath($info['main']) ? ($item . '/' . $info['main']) : $info['main'];
|
||||
} else {
|
||||
$main_file = self::matchDefaultEntry($item);
|
||||
}
|
||||
|
||||
// 检查有没有 composer.json 和 vendor/autoload.php 自动加载,如果有的话,那就写上去
|
||||
$composer_file = $item . '/composer.json';
|
||||
if (is_file(zm_dir($composer_file))) {
|
||||
// composer.json 存在,那么就加载这个插件
|
||||
$composer = json_decode(file_get_contents($composer_file), true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
logger()->error('插件 composer.json 文件解析失败: ' . json_last_error_msg());
|
||||
continue;
|
||||
}
|
||||
if (isset($composer['autoload']['psr-4']) && is_assoc_array($composer['autoload']['psr-4'])) {
|
||||
$plugin_meta['autoload'] = $composer['autoload']['psr-4'];
|
||||
}
|
||||
}
|
||||
|
||||
// 主文件存在,则加载
|
||||
if (is_file(zm_dir($main_file))) {
|
||||
// 如果入口文件存在,那么就加载这个插件
|
||||
$plugin_meta['entry_file'] = $main_file;
|
||||
}
|
||||
|
||||
// composer.json 不存在,那么就忽略这个插件,并报 warning
|
||||
if (!is_file(zm_dir($composer_file)) && $plugin_meta['entry_file'] === null) {
|
||||
logger()->warning('插件 ' . $item . ' 不存在入口文件,也没有自动加载文件和内建 Composer,跳过加载');
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
$plugin_meta['name'] = '<unnamed:' . pathinfo($item, PATHINFO_BASENAME) . '>';
|
||||
// 到这里,说明没有 zmplugin.json 这个文件,那么我们就直接匹配
|
||||
$main_file = self::matchDefaultEntry($item);
|
||||
if (is_file(zm_dir($main_file))) {
|
||||
// 如果入口文件存在,那么就加载这个插件
|
||||
$plugin_meta['entry_file'] = $main_file;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
// 先看有没有 zmplugin.json,没有则不是正常的插件,发个 notice 然后跳过
|
||||
$meta_file = $item . '/zmplugin.json';
|
||||
if (!is_file($meta_file)) {
|
||||
logger()->notice('插件目录 {dir} 没有插件元信息(zmplugin.json),跳过扫描。', ['dir' => $item]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 到这里,说明插件信息收集齐了,只需要加载就行了
|
||||
self::addPlugin($plugin_meta);
|
||||
// 检验元信息是否合法,不合法发个 notice 然后跳过
|
||||
$json_meta = json_decode(file_get_contents($meta_file), true);
|
||||
if (!is_array($json_meta)) {
|
||||
logger()->notice('插件目录 {dir} 的插件元信息(zmplugin.json)不是有效的 JSON,跳过扫描。', ['dir' => $item]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 构造一个元信息对象
|
||||
$meta = new PluginMeta($json_meta, ZM_PLUGIN_TYPE_SOURCE, $item);
|
||||
if ($meta->getEntryFile() === null && $meta->getAutoloadFile() === null) {
|
||||
logger()->notice('插件 ' . $item . ' 不存在入口文件,也没有自动加载文件和内建 Composer,跳过加载');
|
||||
continue;
|
||||
}
|
||||
|
||||
// 添加插件到全局列表
|
||||
self::addPlugin($meta);
|
||||
++$cnt;
|
||||
}
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加插件到全局注册中
|
||||
* 添加一个 Phar 文件形式的插件
|
||||
*
|
||||
* @throws PluginException
|
||||
*/
|
||||
public static function addPlugin(array $meta = []): void
|
||||
public static function addPluginFromPhar(string $phar_path): void
|
||||
{
|
||||
if (!isset($meta['name'])) {
|
||||
throw new PluginException('Plugin must have a name!');
|
||||
}
|
||||
logger()->debug('Adding plugin: ' . $meta['name']);
|
||||
|
||||
self::$plugins[$meta['name']] = $meta;
|
||||
|
||||
// 存在直接声明的对象,那么直接初始化
|
||||
if (isset($meta['object']) && $meta['object'] instanceof ZMPlugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 存在入口文件(单文件),从单文件加载
|
||||
if (isset($meta['entry_file']) && is_file(zm_dir($meta['entry_file']))) {
|
||||
$zmplugin = self::$plugins[$meta['name']]['object'] = require $meta['entry_file'];
|
||||
if (!$zmplugin instanceof ZMPlugin) {
|
||||
unset(self::$plugins[$meta['name']]);
|
||||
throw new PluginException('插件 ' . $meta['name'] . ' 的入口文件 ' . $meta['entry_file'] . ' 必须返回一个 ZMPlugin 对象');
|
||||
$meta = [];
|
||||
try {
|
||||
// 加载这个 Phar 文件
|
||||
$phar = require $phar_path;
|
||||
// 读取元信息
|
||||
$plugin_file_path = zm_dir('phar://' . $phar_path . '/zmplugin.json');
|
||||
if (!file_exists($plugin_file_path)) {
|
||||
throw new PluginException('插件元信息 zmplugin.json 文件不存在');
|
||||
}
|
||||
return;
|
||||
// 解析元信息的 JSON
|
||||
$meta_json = json_decode(file_get_contents($plugin_file_path), true);
|
||||
// 失败抛出异常
|
||||
if (!is_array($meta_json)) {
|
||||
throw new PluginException('插件信息文件解析失败');
|
||||
}
|
||||
// $phar 这时应该是一个 ZMPlugin 对象,写入元信息
|
||||
$meta = new PluginMeta($meta_json, ZM_PLUGIN_TYPE_PHAR, zm_dir('phar://' . $phar_path));
|
||||
// 如果已经返回了一个插件对象,那么直接塞进去实体
|
||||
if ($phar instanceof ZMPlugin) {
|
||||
$meta->bindEntity($phar);
|
||||
}
|
||||
// 添加到插件列表
|
||||
self::addPlugin($meta);
|
||||
} catch (\Throwable $e) {
|
||||
throw new PluginException('Phar 插件 ' . $phar_path . ' 加载失败: ' . $e->getMessage(), previous: $e);
|
||||
}
|
||||
}
|
||||
|
||||
// 存在自动加载,检测 vendor/autoload.php 是否存在,如果存在,那么就加载
|
||||
if (isset($meta['autoload'], $meta['dir']) && $meta['dir'] !== '' && is_file($meta['dir'] . '/vendor/autoload.php')) {
|
||||
require_once $meta['dir'] . '/vendor/autoload.php';
|
||||
return;
|
||||
/**
|
||||
* 从 Composer 添加插件
|
||||
* @throws PluginException
|
||||
*/
|
||||
public static function addPluginsFromComposer(): int
|
||||
{
|
||||
$installed_file = SOURCE_ROOT_DIR . '/vendor/composer/installed.json';
|
||||
if (!file_exists($installed_file)) {
|
||||
logger()->notice('找不到 Composer 的 installed.json 文件,跳过扫描 Composer 插件');
|
||||
return 0;
|
||||
}
|
||||
// 如果都不存在,那是不可能的事情,抛出一个谁都没见过的异常
|
||||
unset(self::$plugins[$meta['name']]);
|
||||
throw new PluginException('插件 ' . $meta['name'] . ' 无法加载,因为没有入口文件,也没有自动加载文件和内建 Composer');
|
||||
$json = json_decode(file_get_contents($installed_file), true);
|
||||
if (!is_array($json)) {
|
||||
logger()->notice('Composer 的 installed.json 文件解析失败,跳过扫描 Composer 插件');
|
||||
return 0;
|
||||
}
|
||||
$cnt = 0;
|
||||
foreach ($json['packages'] as $item) {
|
||||
$root_dir = SOURCE_ROOT_DIR . '/vendor/' . $item['name'];
|
||||
$meta_file = zm_dir($root_dir . '/zmplugin.json');
|
||||
if (!file_exists($meta_file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检验元信息是否合法,不合法发个 notice 然后跳过
|
||||
$json_meta = json_decode(file_get_contents($meta_file), true);
|
||||
if (!is_array($json_meta)) {
|
||||
logger()->notice('插件目录 {dir} 的插件元信息(zmplugin.json)不是有效的 JSON,跳过扫描。', ['dir' => $item]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 构造一个元信息对象
|
||||
$meta = new PluginMeta($json_meta, ZM_PLUGIN_TYPE_COMPOSER, zm_dir($root_dir));
|
||||
if ($meta->getEntryFile() === null && $meta->getAutoloadFile() === null) {
|
||||
logger()->notice('插件 ' . $item . ' 不存在入口文件,也没有自动加载文件和内建 Composer,跳过加载');
|
||||
continue;
|
||||
}
|
||||
|
||||
// 添加插件到全局列表
|
||||
self::addPlugin($meta);
|
||||
++$cnt;
|
||||
}
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据插件元信息对象添加一个插件到框架的全局插件库中
|
||||
*
|
||||
* @throws PluginException
|
||||
*/
|
||||
public static function addPlugin(PluginMeta $meta): void
|
||||
{
|
||||
logger()->debug('Adding plugin: ' . $meta->getName());
|
||||
// 首先看看有没有 entity,如果还没有 entity,且 entry_file 有东西,那么就从 entry_file 获取 ZMPlugin 对象
|
||||
if ($meta->getEntity() === null) {
|
||||
if (($entry_file = $meta->getEntryFile()) !== null) {
|
||||
$entity = require $entry_file;
|
||||
if ($entity instanceof ZMPlugin) {
|
||||
$meta->bindEntity($entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果设置了 ZMPlugin entity,并且已设置了 PluginLoad 事件,那就回调
|
||||
// 接下来看看有没有 autoload,有的话 require_once 一下
|
||||
if (($autoload = $meta->getAutoloadFile()) !== null) {
|
||||
require_once $autoload;
|
||||
}
|
||||
// 如果既没有 entity,也没有 autoload,那就要抛出异常了
|
||||
if ($meta->getEntity() === null && $meta->getAutoloadFile() === null) {
|
||||
throw new PluginException('插件 ' . $meta->getName() . ' 既没有入口文件,也没有自动加载文件,无法加载');
|
||||
}
|
||||
// 检查同名插件,如果有同名插件,则抛出异常
|
||||
if (isset(self::$plugins[$meta->getName()])) {
|
||||
throw new PluginException('插件 ' . $meta->getName() . ' 已经存在,无法加载同名插件或重复加载!');
|
||||
}
|
||||
self::$plugins[$meta->getName()] = $meta;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,59 +194,88 @@ class PluginManager
|
||||
*/
|
||||
public static function enablePlugins(AnnotationParser $parser): void
|
||||
{
|
||||
foreach (self::$plugins as $name => $plugin) {
|
||||
if (!isset($plugin['internal'])) {
|
||||
foreach (self::$plugins as $name => $meta) {
|
||||
// 除了内建插件外,输出 log 告知启动插件
|
||||
if ($meta->getPluginType() !== ZM_PLUGIN_TYPE_NATIVE) {
|
||||
logger()->info('Enabling plugin: ' . $name);
|
||||
}
|
||||
// 先判断下依赖关系,如果声明了依赖,但依赖不合规直接报错崩溃
|
||||
foreach (($plugin['dependencies'] ?? []) as $dep_name => $dep_version) {
|
||||
// 先判断依赖关系,如果声明了依赖,但依赖不合规则报错崩溃
|
||||
foreach ($meta->getDependencies() as $dep_name => $dep_version) {
|
||||
// 缺少依赖的插件,不行
|
||||
if (!isset(self::$plugins[$dep_name])) {
|
||||
throw new PluginException('插件 ' . $name . ' 依赖插件 ' . $dep_name . ',但是没有找到这个插件');
|
||||
}
|
||||
if (VersionComparator::compareVersionRange(self::$plugins[$dep_name]['version'] ?? '1.0', $dep_version) === false) {
|
||||
// 依赖的插件版本不对,不行
|
||||
if (VersionComparator::compareVersionRange(self::$plugins[$dep_name]->getVersion(), $dep_version) === false) {
|
||||
throw new PluginException('插件 ' . $name . ' 依赖插件 ' . $dep_name . ',但是这个插件的版本不符合要求');
|
||||
}
|
||||
}
|
||||
if (isset($plugin['object']) && $plugin['object'] instanceof ZMPlugin) {
|
||||
$obj = $plugin['object'];
|
||||
// 如果插件为单文件形式,且设置了 pluginLoad 事件,那就调用
|
||||
$meta->getEntity()?->emitPluginLoad($parser);
|
||||
if (($entity = $meta->getEntity()) instanceof ZMPlugin) {
|
||||
// 将 BotAction 加入事件监听
|
||||
foreach ($entity->getBotActions() as $action) {
|
||||
AnnotationMap::addSingleAnnotation($action);
|
||||
$parser->parseSpecial($action);
|
||||
}
|
||||
// 将 BotCommand 加入事件监听
|
||||
foreach ($entity->getBotCommands() as $cmd) {
|
||||
AnnotationMap::addSingleAnnotation($cmd);
|
||||
$parser->parseSpecial($cmd);
|
||||
}
|
||||
// 将 Event 加入事件监听
|
||||
foreach ($obj->getEvents() as $event) {
|
||||
foreach ($entity->getEvents() as $event) {
|
||||
$bind = new BindEvent($event[0], $event[2]);
|
||||
$bind->on($event[1]);
|
||||
AnnotationMap::$_list[BindEvent::class][] = $bind;
|
||||
AnnotationMap::addSingleAnnotation($bind);
|
||||
}
|
||||
// 将 Routes 加入事件监听
|
||||
foreach ($obj->getRoutes() as $route) {
|
||||
foreach ($entity->getRoutes() as $route) {
|
||||
$parser->parseSpecial($route);
|
||||
}
|
||||
// 将 BotEvents 加入事件监听
|
||||
foreach ($obj->getBotEvents() as $event) {
|
||||
AnnotationMap::$_list[BotEvent::class][] = $event;
|
||||
foreach ($entity->getBotEvents() as $event) {
|
||||
AnnotationMap::addSingleAnnotation($event);
|
||||
}
|
||||
// 将 BotCommand 加入事件监听
|
||||
foreach ($obj->getBotCommands() as $cmd) {
|
||||
AnnotationMap::$_list[BotCommand::class][] = $cmd;
|
||||
$parser->parseSpecial($cmd);
|
||||
// 将 Cron 加入注解
|
||||
foreach ($entity->getCrons() as $cron) {
|
||||
AnnotationMap::addSingleAnnotation($cron);
|
||||
$parser->parseSpecial($cron);
|
||||
}
|
||||
} elseif (isset($plugin['autoload'], $plugin['dir'])) {
|
||||
foreach ($plugin['autoload'] as $k => $v) {
|
||||
$parser->addPsr4Path($plugin['dir'] . '/' . $v . '/', trim($k, '\\'));
|
||||
// 设置 @Init 注解
|
||||
foreach ($entity->getInits() as $init) {
|
||||
AnnotationMap::addSingleAnnotation($init);
|
||||
}
|
||||
}
|
||||
// 如果设置了 Autoload file,那么将会把 psr-4 的加载路径丢进 parser
|
||||
foreach ($meta->getAutoloadPsr4() as $namespace => $path) {
|
||||
$parser->addPsr4Path($meta->getRootDir() . '/' . $path . '/', trim($namespace, '\\'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function matchDefaultEntry(string $dir): string
|
||||
/**
|
||||
* 打包插件到 Phar
|
||||
*
|
||||
* @throws PluginException
|
||||
*/
|
||||
public static function packPlugin(string $name): string
|
||||
{
|
||||
$main = '';
|
||||
// 没有设置入口文件,则遍历默认入口文件列表
|
||||
foreach (self::$default_entries as $entry) {
|
||||
$main_file = $dir . '/' . $entry;
|
||||
if (is_file(zm_dir($main_file))) {
|
||||
$main = $main_file;
|
||||
break;
|
||||
}
|
||||
// 先遍历下插件目录下是否有这个插件,没有这个插件则不能打包
|
||||
$plugin_dir = config('global.plugin.load_dir', SOURCE_ROOT_DIR . '/plugins');
|
||||
// 模拟加载一遍插件
|
||||
self::addPluginsFromDir($plugin_dir);
|
||||
|
||||
// 必须是源码模式才行
|
||||
if (!isset(self::$plugins[$name]) || self::$plugins[$name]->getPluginType() !== ZM_PLUGIN_TYPE_SOURCE) {
|
||||
throw new PluginException("没有找到名字为 {$name} 的插件(要打包的插件必须是源码模式)。");
|
||||
}
|
||||
return $main;
|
||||
|
||||
$plugin = self::$plugins[$name];
|
||||
// 插件目录
|
||||
$dir = $plugin->getRootDir();
|
||||
// TODO: 写到这了
|
||||
// 插件加载方式判断
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
173
src/ZM/Plugin/PluginMeta.php
Normal file
173
src/ZM/Plugin/PluginMeta.php
Normal file
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin;
|
||||
|
||||
use ZM\Exception\PluginException;
|
||||
|
||||
/**
|
||||
* 插件的元信息对象,对应 zmplugin.json
|
||||
*/
|
||||
class PluginMeta implements \JsonSerializable
|
||||
{
|
||||
/** @var string 插件名称 */
|
||||
private string $name;
|
||||
|
||||
/** @var string 插件版本 */
|
||||
private string $version;
|
||||
|
||||
/** @var string 插件描述 */
|
||||
private string $description;
|
||||
|
||||
/** @var array 插件的依赖列表 */
|
||||
private array $dependencies;
|
||||
|
||||
/** @var null|string 插件的根目录 */
|
||||
private ?string $root_dir;
|
||||
|
||||
/** @var int 插件类型 */
|
||||
private int $plugin_type;
|
||||
|
||||
/** @var array 元信息原文 */
|
||||
private array $metas;
|
||||
|
||||
private ?ZMPlugin $entity = null;
|
||||
|
||||
/**
|
||||
* @param array $meta 元信息数组格式
|
||||
* @param int $plugin_type 插件类型
|
||||
* @param null|string $root_dir 插件根目录
|
||||
*/
|
||||
public function __construct(array $meta, int $plugin_type = ZM_PLUGIN_TYPE_NATIVE, ?string $root_dir = null)
|
||||
{
|
||||
// 设置名称
|
||||
$this->name = $meta['name'] ?? '<anonymous>';
|
||||
// 设置版本
|
||||
$this->version = $meta['version'] ?? '1.0.0';
|
||||
// 设置描述
|
||||
$this->description = $meta['description'] ?? '';
|
||||
// 设置依赖
|
||||
$this->dependencies = $meta['dependencies'] ?? [];
|
||||
$this->metas = $meta;
|
||||
// 设置插件根目录
|
||||
$this->plugin_type = $plugin_type;
|
||||
// 设置插件类型
|
||||
$this->root_dir = $root_dir;
|
||||
}
|
||||
|
||||
public function bindEntity(ZMPlugin $plugin): void
|
||||
{
|
||||
$this->entity = $plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该插件的入口文件(如果存在的话)
|
||||
*/
|
||||
public function getEntryFile(): ?string
|
||||
{
|
||||
// 没传入插件目录的话,直接返回空
|
||||
if ($this->root_dir === null) {
|
||||
return null;
|
||||
}
|
||||
// 首先看看元信息中有没有 main 字段指定,没有就从 default 里找
|
||||
$main = zm_dir($this->root_dir . '/' . ($this->metas['main'] ?? 'main.php'));
|
||||
if (file_exists($main)) {
|
||||
return $main;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该插件的 Composer 自动加载文件(如果存在的话)
|
||||
*/
|
||||
public function getAutoloadFile(): ?string
|
||||
{
|
||||
// 没传入插件目录的话,直接返回空
|
||||
if ($this->root_dir === null) {
|
||||
return null;
|
||||
}
|
||||
return match ($this->plugin_type) {
|
||||
ZM_PLUGIN_TYPE_PHAR, ZM_PLUGIN_TYPE_SOURCE => file_exists($dir = zm_dir($this->root_dir . '/vendor/autoload.php')) ? $dir : null,
|
||||
ZM_PLUGIN_TYPE_NATIVE, ZM_PLUGIN_TYPE_COMPOSER => zm_dir(SOURCE_ROOT_DIR . '/vendor/autoload.php'),
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该插件的 Composer 自动加载 PSR-4 列表
|
||||
*
|
||||
* @throws PluginException 无法加载 composer.json 时抛出异常
|
||||
*/
|
||||
public function getAutoloadPsr4(): array
|
||||
{
|
||||
// 没传入插件目录的话,直接返回空
|
||||
if ($this->root_dir === null) {
|
||||
return [];
|
||||
}
|
||||
// 先找有没有 composer.json,没有的话就返回空列表
|
||||
if (!file_exists(zm_dir($this->root_dir . '/composer.json'))) {
|
||||
return [];
|
||||
}
|
||||
// 有,但是 composer.json 是坏的,抛出一个异常
|
||||
if (($composer = json_decode(file_get_contents(zm_dir($this->root_dir . '/composer.json')), true)) === null) {
|
||||
throw new PluginException("Bad composer.json in plugin {$this->name}");
|
||||
}
|
||||
return $composer['autoload']['psr-4'] ?? [];
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getVersion(): string
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function getDependencies(): array
|
||||
{
|
||||
return $this->dependencies;
|
||||
}
|
||||
|
||||
public function getRootDir(): string
|
||||
{
|
||||
return $this->root_dir;
|
||||
}
|
||||
|
||||
public function setRootDir(string $root_dir): void
|
||||
{
|
||||
$this->root_dir = $root_dir;
|
||||
}
|
||||
|
||||
public function getPluginType(): int
|
||||
{
|
||||
return $this->plugin_type;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->name,
|
||||
'version' => $this->version,
|
||||
'description' => $this->description,
|
||||
'dependencies' => $this->dependencies,
|
||||
];
|
||||
}
|
||||
|
||||
public function getMetas(): array
|
||||
{
|
||||
return $this->metas;
|
||||
}
|
||||
|
||||
public function getEntity(): ?ZMPlugin
|
||||
{
|
||||
return $this->entity;
|
||||
}
|
||||
}
|
||||
25
src/ZM/Plugin/Traits/BotActionTrait.php
Normal file
25
src/ZM/Plugin/Traits/BotActionTrait.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\OneBot\BotAction;
|
||||
|
||||
trait BotActionTrait
|
||||
{
|
||||
protected array $bot_actions = [];
|
||||
|
||||
public function onBotAction(BotAction $bot_action_annotation): void
|
||||
{
|
||||
$this->bot_actions[] = $bot_action_annotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getBotActions(): array
|
||||
{
|
||||
return $this->bot_actions;
|
||||
}
|
||||
}
|
||||
28
src/ZM/Plugin/Traits/BotCommandTrait.php
Normal file
28
src/ZM/Plugin/Traits/BotCommandTrait.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\OneBot\BotCommand;
|
||||
|
||||
trait BotCommandTrait
|
||||
{
|
||||
/** @var array 机器人指令列表 */
|
||||
protected array $bot_commands = [];
|
||||
|
||||
/**
|
||||
* 添加一个 OneBot 机器人命令
|
||||
*
|
||||
* @param BotCommand $command BotCommand 注解对象
|
||||
*/
|
||||
public function addBotCommand(BotCommand $command): void
|
||||
{
|
||||
$this->bot_commands[] = $command;
|
||||
}
|
||||
|
||||
public function getBotCommands(): array
|
||||
{
|
||||
return $this->bot_commands;
|
||||
}
|
||||
}
|
||||
27
src/ZM/Plugin/Traits/BotEventTrait.php
Normal file
27
src/ZM/Plugin/Traits/BotEventTrait.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\OneBot\BotEvent;
|
||||
|
||||
trait BotEventTrait
|
||||
{
|
||||
/** @var array 机器人事件列表 */
|
||||
protected array $bot_events = [];
|
||||
|
||||
/**
|
||||
* 添加一个 OneBot 机器人事件
|
||||
* @param BotEvent $event BotEvent 注解对象
|
||||
*/
|
||||
public function addBotEvent(BotEvent $event): void
|
||||
{
|
||||
$this->bot_events[] = $event;
|
||||
}
|
||||
|
||||
public function getBotEvents(): array
|
||||
{
|
||||
return $this->bot_events;
|
||||
}
|
||||
}
|
||||
31
src/ZM/Plugin/Traits/CronTrait.php
Normal file
31
src/ZM/Plugin/Traits/CronTrait.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\Framework\Cron;
|
||||
|
||||
trait CronTrait
|
||||
{
|
||||
/** @var Cron[] 计划任务列表 */
|
||||
protected array $crons = [];
|
||||
|
||||
/**
|
||||
* 添加一个计划任务
|
||||
*
|
||||
* @param Cron $cron 计划任务注解对象
|
||||
*/
|
||||
public function addCron(Cron $cron): void
|
||||
{
|
||||
$this->crons[] = $cron;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getCrons(): array
|
||||
{
|
||||
return $this->crons;
|
||||
}
|
||||
}
|
||||
27
src/ZM/Plugin/Traits/EventTrait.php
Normal file
27
src/ZM/Plugin/Traits/EventTrait.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
trait EventTrait
|
||||
{
|
||||
/** @var array 全局的事件列表 */
|
||||
protected array $events = [];
|
||||
|
||||
/**
|
||||
* 添加一个框架底层的事件
|
||||
*/
|
||||
public function addEvent(string $event_name, callable $callback, int $level = 20): void
|
||||
{
|
||||
$this->events[] = [$event_name, $callback, $level];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getEvents(): array
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
}
|
||||
37
src/ZM/Plugin/Traits/InitTrait.php
Normal file
37
src/ZM/Plugin/Traits/InitTrait.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\Framework\Init;
|
||||
|
||||
trait InitTrait
|
||||
{
|
||||
/** @var Init[] 插件启动回调 */
|
||||
protected array $on_init = [];
|
||||
|
||||
/**
|
||||
* 设置当前插件的加载后的初始化回调
|
||||
*
|
||||
* @param callable $callback 回调函数
|
||||
* @param int $worker_id 所在的 Worker 进程,默认在 #0
|
||||
* @param int $level 优先级
|
||||
*/
|
||||
public function onInit(callable $callback, int $worker_id = 0, int $level = 20): void
|
||||
{
|
||||
$init = new Init($worker_id, $level);
|
||||
$init->on($callback);
|
||||
$this->on_init[] = $init;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取初始化注解事件回调
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function getInits(): array
|
||||
{
|
||||
return $this->on_init;
|
||||
}
|
||||
}
|
||||
36
src/ZM/Plugin/Traits/PluginLoadTrait.php
Normal file
36
src/ZM/Plugin/Traits/PluginLoadTrait.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\AnnotationParser;
|
||||
|
||||
trait PluginLoadTrait
|
||||
{
|
||||
/** @var null|mixed 插件加载时的回调 */
|
||||
protected mixed $on_plugin_load = null;
|
||||
|
||||
/**
|
||||
* 设置当前插件的插件加载前回调
|
||||
*
|
||||
* @param callable $callback 回调函数
|
||||
*/
|
||||
public function onPluginLoad(callable $callback): void
|
||||
{
|
||||
$this->on_plugin_load = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用插件加载前回调(需要在解析插件的注解时调用,并传入注解解析器)
|
||||
*
|
||||
* @param AnnotationParser $parser 注解解析器
|
||||
* @internal
|
||||
*/
|
||||
public function emitPluginLoad(AnnotationParser $parser): void
|
||||
{
|
||||
if (is_callable($this->on_plugin_load)) {
|
||||
($this->on_plugin_load)($parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/ZM/Plugin/Traits/RouteTrait.php
Normal file
31
src/ZM/Plugin/Traits/RouteTrait.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin\Traits;
|
||||
|
||||
use ZM\Annotation\Http\Route;
|
||||
|
||||
trait RouteTrait
|
||||
{
|
||||
/** @var array 注册的路由列表 */
|
||||
protected array $routes = [];
|
||||
|
||||
/**
|
||||
* 添加一个 HTTP 路由
|
||||
*
|
||||
* @param Route $route Route 注解对象
|
||||
*/
|
||||
public function addHttpRoute(Route $route): void
|
||||
{
|
||||
$this->routes[] = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function getRoutes(): array
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
}
|
||||
@ -4,77 +4,17 @@ declare(strict_types=1);
|
||||
|
||||
namespace ZM\Plugin;
|
||||
|
||||
use ZM\Annotation\Http\Route;
|
||||
use ZM\Annotation\OneBot\BotCommand;
|
||||
use ZM\Annotation\OneBot\BotEvent;
|
||||
|
||||
/**
|
||||
* 单文件插件声明类
|
||||
*/
|
||||
class ZMPlugin
|
||||
{
|
||||
/** @var string 插件目录 */
|
||||
protected string $dir;
|
||||
|
||||
/** @var array 机器人事件列表 */
|
||||
protected array $bot_events = [];
|
||||
|
||||
/** @var array 机器人指令列表 */
|
||||
protected array $bot_commands = [];
|
||||
|
||||
/** @var array 全局的事件列表 */
|
||||
protected array $events = [];
|
||||
|
||||
/** @var array 注册的路由列表 */
|
||||
protected array $routes = [];
|
||||
|
||||
public function __construct(string $dir)
|
||||
{
|
||||
$this->dir = $dir;
|
||||
}
|
||||
|
||||
public function getDir(): string
|
||||
{
|
||||
return $this->dir;
|
||||
}
|
||||
|
||||
public function addBotEvent(BotEvent $event)
|
||||
{
|
||||
$this->bot_events[] = $event;
|
||||
}
|
||||
|
||||
public function addBotCommand(BotCommand $command)
|
||||
{
|
||||
$this->bot_commands[] = $command;
|
||||
}
|
||||
|
||||
public function addEvent(string $event_name, callable $callback, int $level = 20)
|
||||
{
|
||||
$this->events[] = [$event_name, $callback, $level];
|
||||
}
|
||||
|
||||
public function addHttpRoute(Route $route)
|
||||
{
|
||||
$this->routes[] = $route;
|
||||
}
|
||||
|
||||
public function getBotEvents(): array
|
||||
{
|
||||
return $this->bot_events;
|
||||
}
|
||||
|
||||
public function getBotCommands(): array
|
||||
{
|
||||
return $this->bot_commands;
|
||||
}
|
||||
|
||||
public function getEvents(): array
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
|
||||
public function getRoutes(): array
|
||||
{
|
||||
return $this->routes;
|
||||
}
|
||||
use Traits\BotActionTrait;
|
||||
use Traits\BotCommandTrait;
|
||||
use Traits\BotEventTrait;
|
||||
use Traits\CronTrait;
|
||||
use Traits\EventTrait;
|
||||
use Traits\InitTrait;
|
||||
use Traits\PluginLoadTrait;
|
||||
use Traits\RouteTrait;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace ZM\Store\KV;
|
||||
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
|
||||
interface KVInterface
|
||||
interface KVInterface extends CacheInterface
|
||||
{
|
||||
public static function open(string $name = ''): CacheInterface;
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ use ZM\Store\FileSystem;
|
||||
/**
|
||||
* 轻量、基于本地 JSON 文件的 KV 键值对缓存
|
||||
*/
|
||||
class LightCache implements CacheInterface, KVInterface
|
||||
class LightCache implements KVInterface
|
||||
{
|
||||
/** @var array 存放库对象的列表 */
|
||||
private static array $objs = [];
|
||||
|
||||
@ -7,7 +7,7 @@ namespace ZM\Store\KV\Redis;
|
||||
use Psr\SimpleCache\CacheInterface;
|
||||
use ZM\Store\KV\KVInterface;
|
||||
|
||||
class KVRedis implements CacheInterface, KVInterface
|
||||
class KVRedis implements KVInterface
|
||||
{
|
||||
private string $pool_name;
|
||||
|
||||
|
||||
@ -7,8 +7,12 @@ namespace ZM;
|
||||
use ZM\Command\Server\ServerStartCommand;
|
||||
use ZM\Exception\SingletonViolationException;
|
||||
use ZM\Plugin\PluginManager;
|
||||
use ZM\Plugin\PluginMeta;
|
||||
use ZM\Plugin\ZMPlugin;
|
||||
|
||||
/**
|
||||
* 这是一个可以将框架以代码形式启动的一个类,且继承于插件,可以以插件的方式绑定事件回调等
|
||||
*/
|
||||
class ZMApplication extends ZMPlugin
|
||||
{
|
||||
/** @var null|ZMApplication 存储单例类的变量 */
|
||||
@ -20,13 +24,12 @@ class ZMApplication extends ZMPlugin
|
||||
/**
|
||||
* @throws SingletonViolationException
|
||||
*/
|
||||
public function __construct(mixed $dir = null)
|
||||
public function __construct()
|
||||
{
|
||||
if (self::$obj !== null) {
|
||||
throw new SingletonViolationException(self::class);
|
||||
}
|
||||
self::$obj = $this; // 用于标记已经初始化完成
|
||||
parent::__construct($dir ?? (__DIR__ . '/../..'));
|
||||
$this->args = ServerStartCommand::exportOptionArray();
|
||||
}
|
||||
|
||||
@ -47,7 +50,9 @@ class ZMApplication extends ZMPlugin
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
PluginManager::addPlugin(['name' => 'native-app', 'object' => $this]);
|
||||
$meta = new PluginMeta(['name' => 'native'], ZM_PLUGIN_TYPE_NATIVE);
|
||||
$meta->bindEntity($this);
|
||||
PluginManager::addPlugin($meta);
|
||||
(new Framework($this->args))->init()->start();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user