diff --git a/config/global.php b/config/global.php index f1c2428b..9d4735db 100644 --- a/config/global.php +++ b/config/global.php @@ -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 遍历加载 ]; /* 内部默认启用的插件 */ diff --git a/docs/update/v3.md b/docs/update/v3.md index ec4e4109..b37e1445 100644 --- a/docs/update/v3.md +++ b/docs/update/v3.md @@ -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**: ## 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**: ## 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**: ## 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**: ## 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**: diff --git a/src/Globals/global_defines_app.php b/src/Globals/global_defines_app.php index 475f6482..a8549ade 100644 --- a/src/Globals/global_defines_app.php +++ b/src/Globals/global_defines_app.php @@ -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 加载 diff --git a/src/Globals/global_functions.php b/src/Globals/global_functions.php index 8b3444d4..2f458192 100644 --- a/src/Globals/global_functions.php +++ b/src/Globals/global_functions.php @@ -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; diff --git a/src/Globals/script_setup_loader.php b/src/Globals/script_setup_loader.php index c86d8ae3..e3aaa997 100644 --- a/src/Globals/script_setup_loader.php +++ b/src/Globals/script_setup_loader.php @@ -33,7 +33,7 @@ function _zm_setup_loader() return true; }); - // TODO: 然后加载插件目录下的插件 + // 这里好像没必要加载插件目录的插件,插件理论上不能在 Master 被加载 // 解析所有注册路径的文件,获取注解 $parser->parse(); diff --git a/src/ZM/Annotation/AnnotationMap.php b/src/ZM/Annotation/AnnotationMap.php index 2f883b38..39f0d05d 100644 --- a/src/ZM/Annotation/AnnotationMap.php +++ b/src/ZM/Annotation/AnnotationMap.php @@ -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 { diff --git a/src/ZM/Annotation/Framework/Cron.php b/src/ZM/Annotation/Framework/Cron.php index 727c5453..ecd5fc81 100644 --- a/src/ZM/Annotation/Framework/Cron.php +++ b/src/ZM/Annotation/Framework/Cron.php @@ -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); + } } diff --git a/src/ZM/Annotation/OneBot/BotAction.php b/src/ZM/Annotation/OneBot/BotAction.php index e151574d..852ca2c1 100644 --- a/src/ZM/Annotation/OneBot/BotAction.php +++ b/src/ZM/Annotation/OneBot/BotAction.php @@ -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; diff --git a/src/ZM/Command/Generate/TextGenerateCommand.php b/src/ZM/Command/Generate/TextGenerateCommand.php index 269f5b4f..3f9f46ae 100644 --- a/src/ZM/Command/Generate/TextGenerateCommand.php +++ b/src/ZM/Command/Generate/TextGenerateCommand.php @@ -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 -> + $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.]+)(?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; + } +} diff --git a/src/ZM/Container/ContainerRegistrant.php b/src/ZM/Container/ContainerRegistrant.php index 1d30e1ab..5b62e26e 100644 --- a/src/ZM/Container/ContainerRegistrant.php +++ b/src/ZM/Container/ContainerRegistrant.php @@ -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'], ), diff --git a/src/ZM/Context/Trait/BotActionTrait.php b/src/ZM/Context/Trait/BotActionTrait.php index b39db513..9250db4a 100644 --- a/src/ZM/Context/Trait/BotActionTrait.php +++ b/src/ZM/Context/Trait/BotActionTrait.php @@ -22,9 +22,9 @@ trait BotActionTrait /** * @var array 一个记录 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; diff --git a/src/ZM/Event/Listener/WorkerEventListener.php b/src/ZM/Event/Listener/WorkerEventListener.php index 70b5b664..e2c9dbc1 100644 --- a/src/ZM/Event/Listener/WorkerEventListener.php +++ b/src/ZM/Event/Listener/WorkerEventListener.php @@ -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) { diff --git a/src/ZM/Plugin/CommandManual/CommandManualPlugin.php b/src/ZM/Plugin/CommandManual/CommandManualPlugin.php index 6e7a89c5..6b928fe7 100644 --- a/src/ZM/Plugin/CommandManual/CommandManualPlugin.php +++ b/src/ZM/Plugin/CommandManual/CommandManualPlugin.php @@ -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'); } diff --git a/src/ZM/Plugin/OneBot12Adapter.php b/src/ZM/Plugin/OneBot12Adapter.php index 42a450ce..4da88d17 100644 --- a/src/ZM/Plugin/OneBot12Adapter.php +++ b/src/ZM/Plugin/OneBot12Adapter.php @@ -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(); diff --git a/src/ZM/Plugin/PluginManager.php b/src/ZM/Plugin/PluginManager.php index eb9facbf..6713dde6 100644 --- a/src/ZM/Plugin/PluginManager.php +++ b/src/ZM/Plugin/PluginManager.php @@ -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' => '', - '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 插件信息列表 */ 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'] ?? (''); - // 设置版本(如果有) - 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'] = ''; - // 到这里,说明没有 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 ''; } } diff --git a/src/ZM/Plugin/PluginMeta.php b/src/ZM/Plugin/PluginMeta.php new file mode 100644 index 00000000..f282fa39 --- /dev/null +++ b/src/ZM/Plugin/PluginMeta.php @@ -0,0 +1,173 @@ +name = $meta['name'] ?? ''; + // 设置版本 + $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; + } +} diff --git a/src/ZM/Plugin/Traits/BotActionTrait.php b/src/ZM/Plugin/Traits/BotActionTrait.php new file mode 100644 index 00000000..b53c46aa --- /dev/null +++ b/src/ZM/Plugin/Traits/BotActionTrait.php @@ -0,0 +1,25 @@ +bot_actions[] = $bot_action_annotation; + } + + /** + * @internal + */ + public function getBotActions(): array + { + return $this->bot_actions; + } +} diff --git a/src/ZM/Plugin/Traits/BotCommandTrait.php b/src/ZM/Plugin/Traits/BotCommandTrait.php new file mode 100644 index 00000000..5789b75f --- /dev/null +++ b/src/ZM/Plugin/Traits/BotCommandTrait.php @@ -0,0 +1,28 @@ +bot_commands[] = $command; + } + + public function getBotCommands(): array + { + return $this->bot_commands; + } +} diff --git a/src/ZM/Plugin/Traits/BotEventTrait.php b/src/ZM/Plugin/Traits/BotEventTrait.php new file mode 100644 index 00000000..330c5127 --- /dev/null +++ b/src/ZM/Plugin/Traits/BotEventTrait.php @@ -0,0 +1,27 @@ +bot_events[] = $event; + } + + public function getBotEvents(): array + { + return $this->bot_events; + } +} diff --git a/src/ZM/Plugin/Traits/CronTrait.php b/src/ZM/Plugin/Traits/CronTrait.php new file mode 100644 index 00000000..257bde52 --- /dev/null +++ b/src/ZM/Plugin/Traits/CronTrait.php @@ -0,0 +1,31 @@ +crons[] = $cron; + } + + /** + * @internal + */ + public function getCrons(): array + { + return $this->crons; + } +} diff --git a/src/ZM/Plugin/Traits/EventTrait.php b/src/ZM/Plugin/Traits/EventTrait.php new file mode 100644 index 00000000..928c0cf2 --- /dev/null +++ b/src/ZM/Plugin/Traits/EventTrait.php @@ -0,0 +1,27 @@ +events[] = [$event_name, $callback, $level]; + } + + /** + * @internal + */ + public function getEvents(): array + { + return $this->events; + } +} diff --git a/src/ZM/Plugin/Traits/InitTrait.php b/src/ZM/Plugin/Traits/InitTrait.php new file mode 100644 index 00000000..75aaefd0 --- /dev/null +++ b/src/ZM/Plugin/Traits/InitTrait.php @@ -0,0 +1,37 @@ +on($callback); + $this->on_init[] = $init; + } + + /** + * 获取初始化注解事件回调 + * + * @internal + */ + public function getInits(): array + { + return $this->on_init; + } +} diff --git a/src/ZM/Plugin/Traits/PluginLoadTrait.php b/src/ZM/Plugin/Traits/PluginLoadTrait.php new file mode 100644 index 00000000..2af6f054 --- /dev/null +++ b/src/ZM/Plugin/Traits/PluginLoadTrait.php @@ -0,0 +1,36 @@ +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); + } + } +} diff --git a/src/ZM/Plugin/Traits/RouteTrait.php b/src/ZM/Plugin/Traits/RouteTrait.php new file mode 100644 index 00000000..61a1c219 --- /dev/null +++ b/src/ZM/Plugin/Traits/RouteTrait.php @@ -0,0 +1,31 @@ +routes[] = $route; + } + + /** + * @internal + */ + public function getRoutes(): array + { + return $this->routes; + } +} diff --git a/src/ZM/Plugin/ZMPlugin.php b/src/ZM/Plugin/ZMPlugin.php index d8a6052b..3ab14f7d 100644 --- a/src/ZM/Plugin/ZMPlugin.php +++ b/src/ZM/Plugin/ZMPlugin.php @@ -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; } diff --git a/src/ZM/Store/KV/KVInterface.php b/src/ZM/Store/KV/KVInterface.php index 1944585d..156c5668 100644 --- a/src/ZM/Store/KV/KVInterface.php +++ b/src/ZM/Store/KV/KVInterface.php @@ -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; } diff --git a/src/ZM/Store/KV/LightCache.php b/src/ZM/Store/KV/LightCache.php index c920e11a..301bb1ab 100644 --- a/src/ZM/Store/KV/LightCache.php +++ b/src/ZM/Store/KV/LightCache.php @@ -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 = []; diff --git a/src/ZM/Store/KV/Redis/KVRedis.php b/src/ZM/Store/KV/Redis/KVRedis.php index f1a2906f..6c1119cf 100644 --- a/src/ZM/Store/KV/Redis/KVRedis.php +++ b/src/ZM/Store/KV/Redis/KVRedis.php @@ -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; diff --git a/src/ZM/ZMApplication.php b/src/ZM/ZMApplication.php index c8ee8d6b..15f5c6a3 100644 --- a/src/ZM/ZMApplication.php +++ b/src/ZM/ZMApplication.php @@ -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(); } }