add cs fixer and PHPStan and activate it (build 436)

This commit is contained in:
crazywhalecc
2022-03-15 18:05:33 +08:00
parent d01bd69aa5
commit 1706afbcd0
163 changed files with 4572 additions and 3588 deletions

6
.gitignore vendored
View File

@@ -13,10 +13,16 @@ composer.lock
/runtime/ /runtime/
/tmp/ /tmp/
/temp/ /temp/
# go-cqhttp快速安装启动相关可能被废弃
/ext/go-cqhttp/data/ /ext/go-cqhttp/data/
/ext/go-cqhttp/logs/ /ext/go-cqhttp/logs/
/ext/go-cqhttp/config.hjson /ext/go-cqhttp/config.hjson
/ext/go-cqhttp/device.json /ext/go-cqhttp/device.json
/ext/go-cqhttp/go-cqhttp /ext/go-cqhttp/go-cqhttp
/ext/go-cqhttp/session.token /ext/go-cqhttp/session.token
.zm_worker_*.pid .zm_worker_*.pid
# Git Hook 的相关锁文件
cghooks.lock

76
.php-cs-fixer.php Normal file
View File

@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
/**
* @since 2.7.0
*/
return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
->setRules([
'@PSR12' => true,
'@Symfony' => true,
'@PhpCsFixer' => true,
'array_syntax' => [
'syntax' => 'short',
],
'list_syntax' => [
'syntax' => 'short',
],
'concat_space' => [
'spacing' => 'one',
],
'blank_line_before_statement' => [
'statements' => [
'declare',
],
],
'ordered_imports' => [
'imports_order' => [
'class',
'function',
'const',
],
'sort_algorithm' => 'alpha',
],
'single_line_comment_style' => [
'comment_types' => [
],
],
'yoda_style' => [
'always_move_variable' => false,
'equal' => false,
'identical' => false,
],
'multiline_whitespace_before_semicolons' => [
'strategy' => 'no_multi_line',
],
'constant_case' => [
'case' => 'lower',
],
'class_attributes_separation' => true,
'combine_consecutive_unsets' => true,
'declare_strict_types' => true,
'linebreak_after_opening_tag' => true,
'lowercase_static_reference' => true,
'no_useless_else' => true,
'no_unused_imports' => true,
'not_operator_with_successor_space' => false,
'not_operator_with_space' => false,
'ordered_class_elements' => true,
'php_unit_strict' => false,
'phpdoc_separation' => false,
'single_quote' => true,
'standardize_not_equals' => true,
'multiline_comment_opening_closing' => true,
'phpdoc_summary' => false,
'class_reference_name_casing' => false,
])
->setFinder(
PhpCsFixer\Finder::create()
->exclude('vendor')
->exclude('docs')
->in(__DIR__ . '/src')
)
->setUsingCache(false);

View File

@@ -6,7 +6,18 @@
"extra": { "extra": {
"exclude_annotate": [ "exclude_annotate": [
"src/ZM" "src/ZM"
] ],
"hooks": {
"post-merge": "composer install",
"pre-commit": [
"echo committing as $(git config user.name)",
"./vendor/bin/php-cs-fixer fix --dry-run --diff ./src"
],
"pre-push": [
"./vendor/bin/php-cs-fixer fix --dry-run --diff ./src",
"composer analyse"
]
}
}, },
"authors": [ "authors": [
{ {
@@ -21,7 +32,7 @@
"bin/watcher" "bin/watcher"
], ],
"require": { "require": {
"php": ">=7.2", "php": "^7.2 || ^7.3 || ^7.4 || ^8.0 || ^8.1",
"ext-json": "*", "ext-json": "*",
"ext-posix": "*", "ext-posix": "*",
"doctrine/annotations": "~1.12 || ~1.4.0", "doctrine/annotations": "~1.12 || ~1.4.0",
@@ -59,8 +70,22 @@
"Custom\\": "src/Custom" "Custom\\": "src/Custom"
} }
}, },
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"require-dev": { "require-dev": {
"swoole/ide-helper": "@dev", "swoole/ide-helper": "@dev",
"phpunit/phpunit": "^8.5 || ^9.0" "phpunit/phpunit": "^8.5 || ^9.0",
"brainmaestro/composer-git-hooks": "^2.8",
"friendsofphp/php-cs-fixer": "^3.2 != 3.7.0",
"phpstan/phpstan": "^1.1"
},
"scripts": {
"post-install-cmd": [
"[ $COMPOSER_DEV_MODE -eq 0 ] || vendor/bin/cghooks add"
],
"analyse": "phpstan analyse --memory-limit 300M -l 0 ./src",
"cs-fix": "php-cs-fixer fix $1"
} }
} }

View File

@@ -1,41 +1,42 @@
<?php <?php
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/** @noinspection PhpComposerExtensionStubsInspection */ /** @noinspection PhpComposerExtensionStubsInspection */
/** bind host */ declare(strict_types=1);
/* bind host */
$config['host'] = '0.0.0.0'; $config['host'] = '0.0.0.0';
/** bind port */ /* bind port */
$config['port'] = 20001; $config['port'] = 20001;
/** 框架开到公网或外部的HTTP访问链接通过 DataProvider::getFrameworkLink() 获取 */ /* 框架开到公网或外部的HTTP访问链接通过 DataProvider::getFrameworkLink() 获取 */
$config['http_reverse_link'] = 'http://127.0.0.1:' . $config['port']; $config['http_reverse_link'] = 'http://127.0.0.1:' . $config['port'];
/** 框架是否启动debug模式当debug模式为true时启用热更新需要安装inotify扩展 */ /* 框架是否启动debug模式当debug模式为true时启用热更新需要安装inotify扩展 */
$config['debug_mode'] = false; $config['debug_mode'] = false;
/** 存放框架内文件数据的目录 */ /* 存放框架内文件数据的目录 */
$config['zm_data'] = realpath(WORKING_DIR) . '/zm_data/'; $config['zm_data'] = realpath(WORKING_DIR) . '/zm_data/';
/** 存放各个模块配置文件的目录 */ /* 存放各个模块配置文件的目录 */
$config['config_dir'] = $config['zm_data'] . 'config/'; $config['config_dir'] = $config['zm_data'] . 'config/';
/** 存放崩溃和运行日志的目录 */ /* 存放崩溃和运行日志的目录 */
$config['crash_dir'] = $config['zm_data'] . 'crash/'; $config['crash_dir'] = $config['zm_data'] . 'crash/';
/** 对应swoole的server->set参数 */ /* 对应swoole的server->set参数 */
$config['swoole'] = [ $config['swoole'] = [
'log_file' => $config['crash_dir'] . 'swoole_error.log', 'log_file' => $config['crash_dir'] . 'swoole_error.log',
//'worker_num' => swoole_cpu_num(), //如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算则可把这里改为1使用全局变量 //'worker_num' => swoole_cpu_num(), //如果你只有一个 OneBot 实例连接到框架并且代码没有复杂的CPU密集计算则可把这里改为1使用全局变量
'dispatch_mode' => 2, //包分配原则,见 https://wiki.swoole.com/#/server/setting?id=dispatch_mode 'dispatch_mode' => 2, //包分配原则,见 https://wiki.swoole.com/#/server/setting?id=dispatch_mode
'max_coroutine' => 300000, 'max_coroutine' => 300000,
'max_wait_time' => 5 'max_wait_time' => 5,
//'task_worker_num' => 4, //'task_worker_num' => 4,
//'task_enable_coroutine' => true //'task_enable_coroutine' => true
]; ];
/* 一些框架与框架运行时设置的调整 */
/** 一些框架与框架运行时设置的调整 */
$config['runtime'] = [ $config['runtime'] = [
'swoole_coroutine_hook_flags' => SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL), 'swoole_coroutine_hook_flags' => SWOOLE_HOOK_ALL & (~SWOOLE_HOOK_CURL),
'swoole_server_mode' => SWOOLE_PROCESS, 'swoole_server_mode' => SWOOLE_PROCESS,
@@ -45,22 +46,22 @@ $config['runtime'] = [
'save_console_log_file' => false, // 改为目标路径,则将 Console 输出的日志保存到文件 'save_console_log_file' => false, // 改为目标路径,则将 Console 输出的日志保存到文件
]; ];
/** 轻量字符串缓存,默认开启 */ /* 轻量字符串缓存,默认开启 */
$config['light_cache'] = [ $config['light_cache'] = [
'size' => 512, //最多允许储存的条数需要2的倍数 'size' => 512, //最多允许储存的条数需要2的倍数
'max_strlen' => 32768, //单行字符串最大长度需要2的倍数 'max_strlen' => 32768, //单行字符串最大长度需要2的倍数
'hash_conflict_proportion' => 0.6, //Hash冲突率越大越好但是需要的内存更多 'hash_conflict_proportion' => 0.6, //Hash冲突率越大越好但是需要的内存更多
'persistence_path' => $config['zm_data'] . '_cache.json', 'persistence_path' => $config['zm_data'] . '_cache.json',
'auto_save_interval' => 900 'auto_save_interval' => 900,
]; ];
/** 大容量跨进程变量存储2.2.0可用) */ /* 大容量跨进程变量存储2.2.0可用) */
$config['worker_cache'] = [ $config['worker_cache'] = [
'worker' => 0, 'worker' => 0,
'transaction_timeout' => 30000 'transaction_timeout' => 30000,
]; ];
/** MySQL数据库连接信息host留空则启动时不创建sql连接池 */ /* MySQL数据库连接信息host留空则启动时不创建sql连接池 */
$config['mysql_config'] = [ $config['mysql_config'] = [
'host' => '', 'host' => '',
'port' => 3306, 'port' => 3306,
@@ -72,54 +73,54 @@ $config['mysql_config'] = [
'pool_size' => 64, 'pool_size' => 64,
'options' => [ 'options' => [
PDO::ATTR_STRINGIFY_FETCHES => false, PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
] ],
]; ];
/** Redis连接信息host留空则启动时不创建Redis连接池 */ /* Redis连接信息host留空则启动时不创建Redis连接池 */
$config['redis_config'] = [ $config['redis_config'] = [
'host' => '', 'host' => '',
'port' => 6379, 'port' => 6379,
'timeout' => 1, 'timeout' => 1,
'db_index' => 0, 'db_index' => 0,
'auth' => '' 'auth' => '',
]; ];
/** onebot连接约定的token */ /* onebot连接约定的token */
$config['access_token'] = ''; $config['access_token'] = '';
/** HTTP服务器固定请求头的返回 */ /* HTTP服务器固定请求头的返回 */
$config['http_header'] = [ $config['http_header'] = [
'Server' => 'zhamao-framework', 'Server' => 'zhamao-framework',
'Content-Type' => 'text/html; charset=utf-8' 'Content-Type' => 'text/html; charset=utf-8',
]; ];
/** HTTP服务器在指定状态码下回复的页面默认 */ /* HTTP服务器在指定状态码下回复的页面默认 */
$config['http_default_code_page'] = [ $config['http_default_code_page'] = [
'404' => '404.html' '404' => '404.html',
]; ];
/** zhamao-framework在框架启动时初始化的atomic们 */ /* zhamao-framework在框架启动时初始化的atomic们 */
$config['init_atomics'] = [ $config['init_atomics'] = [
//'custom_atomic_name' => 0, //自定义添加的Atomic //'custom_atomic_name' => 0, //自定义添加的Atomic
]; ];
/** 终端日志显示等级0-4 */ /* 终端日志显示等级0-4 */
$config['info_level'] = 2; $config['info_level'] = 2;
/** 上下文接口类 implemented from ContextInterface */ /* 上下文接口类 implemented from ContextInterface */
$config['context_class'] = \ZM\Context\Context::class; $config['context_class'] = \ZM\Context\Context::class;
/** 静态文件访问 */ /* 静态文件访问 */
$config['static_file_server'] = [ $config['static_file_server'] = [
'status' => false, 'status' => false,
'document_root' => realpath(__DIR__ . '/../') . '/resources/html', 'document_root' => realpath(__DIR__ . '/../') . '/resources/html',
'document_index' => [ 'document_index' => [
'index.html' 'index.html',
] ],
]; ];
/** 机器人解析模块关闭后无法使用如CQCommand等注解(上面的modules即将废弃) */ /* 机器人解析模块关闭后无法使用如CQCommand等注解(上面的modules即将废弃) */
$config['onebot'] = [ $config['onebot'] = [
'status' => true, 'status' => true,
'single_bot_mode' => false, 'single_bot_mode' => false,
@@ -128,18 +129,18 @@ $config['onebot'] = [
'message_command_policy' => 'interrupt', 'message_command_policy' => 'interrupt',
]; ];
/** 一个远程简易终端使用nc直接连接即可但是不建议开放host为0.0.0.0(远程连接) */ /* 一个远程简易终端使用nc直接连接即可但是不建议开放host为0.0.0.0(远程连接) */
$config['remote_terminal'] = [ $config['remote_terminal'] = [
'status' => false, 'status' => false,
'host' => '127.0.0.1', 'host' => '127.0.0.1',
'port' => 20002, 'port' => 20002,
'token' => '' 'token' => '',
]; ];
/** 模块(插件)加载器的相关设置 */ /* 模块(插件)加载器的相关设置 */
$config['module_loader'] = [ $config['module_loader'] = [
'enable_hotload' => false, 'enable_hotload' => false,
'load_path' => $config['zm_data'] . 'modules' 'load_path' => $config['zm_data'] . 'modules',
]; ];
return $config; return $config;

View File

@@ -1,6 +1,8 @@
<?php <?php
require_once "vendor/autoload.php"; declare(strict_types=1);
require_once 'vendor/autoload.php';
use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Swoole\OnOpenEvent; use ZM\Annotation\Swoole\OnOpenEvent;
@@ -9,17 +11,16 @@ use ZM\Console\Console;
use ZM\Module\InstantModule; use ZM\Module\InstantModule;
use ZM\ZMServer; use ZM\ZMServer;
$weather = new InstantModule("weather"); $weather = new InstantModule('weather');
$weather->onEvent(OnOpenEvent::class, ['connect_type' => 'qq'], function (ConnectionObject $conn) {
$weather->onEvent(OnOpenEvent::class, ['connect_type' => 'qq'], function(ConnectionObject $conn) { Console::info('机器人 ' . $conn->getOption('connect_id') . ' 已连接!');
Console::info("机器人 " . $conn->getOption("connect_id") . " 已连接!");
}); });
$weather->onEvent(CQCommand::class, ['match' => '你好'], function() { $weather->onEvent(CQCommand::class, ['match' => '你好'], function () {
ctx()->reply("hello呀"); ctx()->reply('hello呀');
}); });
$app = new ZMServer("app-name"); $app = new ZMServer('app-name');
$app->addModule($weather); $app->addModule($weather);
$app->run(); $app->run();

7
phpstan.neon Normal file
View File

@@ -0,0 +1,7 @@
parameters:
reportUnmatchedIgnoredErrors: false
level: 0
paths:
- ./src/
ignoreErrors:
- '#Used constant OS_TYPE_(LINUX|WINDOWS) not found#'

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace Custom\Annotation; namespace Custom\Annotation;
@@ -11,7 +12,6 @@ use ZM\Annotation\Interfaces\CustomAnnotation;
* Class CustomAnnotation * Class CustomAnnotation
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
* @package Custom\Annotation
*/ */
class Example extends AnnotationBase implements CustomAnnotation class Example extends AnnotationBase implements CustomAnnotation
{ {

View File

@@ -1,11 +1,10 @@
<?php /** @noinspection PhpFullyQualifiedNameUsageInspection */ #plain <?php
//这里写你的全局函数 declare(strict_types=1);
/**
* @param callable $func use ZM\Utils\CoroutinePool;
* @param string $name
* @noinspection PhpUnused function pgo(callable $func, string $name = 'default')
*/ {
function pgo(callable $func, $name = "default") { CoroutinePool::go($func, $name);
\ZM\Utils\CoroutinePool::go($func, $name);
} }

View File

@@ -1,20 +1,22 @@
<?php /** @noinspection PhpMissingReturnTypeInspection */ <?php
declare(strict_types=1);
namespace Module\Example; namespace Module\Example;
use ZM\Annotation\CQ\CQBefore; use ZM\Annotation\CQ\CQBefore;
use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\CQ\CQMessage; use ZM\Annotation\CQ\CQMessage;
use ZM\Annotation\Http\Middleware; use ZM\Annotation\Http\Middleware;
use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Swoole\OnCloseEvent; use ZM\Annotation\Swoole\OnCloseEvent;
use ZM\Annotation\Swoole\OnOpenEvent; use ZM\Annotation\Swoole\OnOpenEvent;
use ZM\Annotation\Swoole\OnRequestEvent; use ZM\Annotation\Swoole\OnRequestEvent;
use ZM\API\CQ; use ZM\API\CQ;
use ZM\API\TuringAPI;
use ZM\API\OneBotV11; use ZM\API\OneBotV11;
use ZM\API\TuringAPI;
use ZM\ConnectionManager\ConnectionObject; use ZM\ConnectionManager\ConnectionObject;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Http\RequestMapping;
use ZM\Event\EventDispatcher; use ZM\Event\EventDispatcher;
use ZM\Exception\InterruptException; use ZM\Exception\InterruptException;
use ZM\Module\QQBot; use ZM\Module\QQBot;
@@ -24,7 +26,6 @@ use ZM\Utils\ZMUtil;
/** /**
* Class Hello * Class Hello
* @package Module\Example
* @since 2.0 * @since 2.0
*/ */
class Hello class Hello
@@ -41,41 +42,49 @@ class Hello
* 使用命令 .reload 发给机器人远程重载,注意将 user_id 换成你自己的 QQ * 使用命令 .reload 发给机器人远程重载,注意将 user_id 换成你自己的 QQ
* @CQCommand(".reload",user_id=627577391) * @CQCommand(".reload",user_id=627577391)
*/ */
public function reload() { public function reload()
ctx()->reply("重启中..."); {
ctx()->reply('重启中...');
ZMUtil::reload(); ZMUtil::reload();
} }
/** /**
* @CQCommand("我是谁") * @CQCommand("我是谁")
*/ */
public function whoami() { public function whoami()
{
$bot = ctx()->getRobot()->getLoginInfo(); $bot = ctx()->getRobot()->getLoginInfo();
$bot_id = $bot["data"]["user_id"]; $bot_id = $bot['data']['user_id'];
$r = OneBotV11::get($bot_id); $r = OneBotV11::get($bot_id);
$QQid = ctx()->getUserId(); $QQid = ctx()->getUserId();
$nick = $r->getStrangerInfo($QQid)["data"]["nickname"]; $nick = $r->getStrangerInfo($QQid)['data']['nickname'];
return "你是" . $nick . "QQ号是" . $QQid; return '你是' . $nick . 'QQ号是' . $QQid;
} }
/** /**
* 向机器人发送"你好啊",也可回复这句话 * 向机器人发送"你好啊",也可回复这句话
* @CQCommand(match="你好",alias={"你好啊","你是谁"}) * @CQCommand(match="你好",alias={"你好啊","你是谁"})
*/ */
public function hello() { public function hello()
return "你好啊,我是由炸毛框架构建的机器人!"; {
return '你好啊,我是由炸毛框架构建的机器人!';
} }
/** /**
* 一个最基本的第三方 API 接口使用示例 * 一个最基本的第三方 API 接口使用示例
* @CQCommand("一言") * @CQCommand("一言")
*/ */
public function hitokoto() { public function hitokoto()
$api_result = ZMRequest::get("https://v1.hitokoto.cn/"); {
if ($api_result === false) return "接口请求出错,请稍后再试!"; $api_result = ZMRequest::get('https://v1.hitokoto.cn/');
if ($api_result === false) {
return '接口请求出错,请稍后再试!';
}
$obj = json_decode($api_result, true); $obj = json_decode($api_result, true);
if ($obj === null) return "接口解析出错!可能返回了非法数据!"; if ($obj === null) {
return $obj["hitokoto"] . "\n----「" . $obj["from"] . ""; return '接口解析出错!可能返回了非法数据!';
}
return $obj['hitokoto'] . "\n----「" . $obj['from'] . '」';
} }
/** /**
@@ -83,33 +92,36 @@ class Hello
* @CQCommand(start_with="机器人",end_with="机器人",message_type="group") * @CQCommand(start_with="机器人",end_with="机器人",message_type="group")
* @CQMessage(message_type="private",level=1) * @CQMessage(message_type="private",level=1)
*/ */
public function turingAPI() { public function turingAPI()
{
$user_id = ctx()->getUserId(); $user_id = ctx()->getUserId();
$api = ""; // 请在这里填入你的图灵机器人的apikey $api = ''; // 请在这里填入你的图灵机器人的apikey
if ($api === "") return false; //如果没有填入apikey则此功能关闭 if ($api === '') {
return false;
} //如果没有填入apikey则此功能关闭
if (($this->_running_annotation ?? null) instanceof CQCommand) { if (($this->_running_annotation ?? null) instanceof CQCommand) {
$msg = ctx()->getFullArg("我在!有什么事吗?"); $msg = ctx()->getFullArg('我在!有什么事吗?');
} else { } else {
$msg = ctx()->getMessage(); $msg = ctx()->getMessage();
} }
ctx()->setMessage($msg); ctx()->setMessage($msg);
if (MessageUtil::matchCommand($msg, ctx()->getData())->status === false) { if (MessageUtil::matchCommand($msg, ctx()->getData())->status === false) {
return TuringAPI::getTuringMsg($msg, $user_id, $api); return TuringAPI::getTuringMsg($msg, $user_id, $api);
} else {
QQBot::getInstance()->handle(ctx()->getData(), ctx()->getCache("level") + 1);
//执行嵌套消息,递归层级+1
return true;
} }
QQBot::getInstance()->handle(ctx()->getData(), ctx()->getCache('level') + 1);
//执行嵌套消息,递归层级+1
return true;
} }
/** /**
* 响应at机器人的消息 * 响应at机器人的消息
* @CQBefore("message") * @CQBefore("message")
*/ */
public function changeAt() { public function changeAt()
{
if (MessageUtil::isAtMe(ctx()->getMessage(), ctx()->getRobotId())) { if (MessageUtil::isAtMe(ctx()->getMessage(), ctx()->getRobotId())) {
$msg = str_replace(CQ::at(ctx()->getRobotId()), "", ctx()->getMessage()); $msg = str_replace(CQ::at(ctx()->getRobotId()), '', ctx()->getMessage());
ctx()->setMessage("机器人" . $msg); ctx()->setMessage('机器人' . $msg);
Console::info(ctx()->getMessage()); Console::info(ctx()->getMessage());
} }
return true; return true;
@@ -123,15 +135,16 @@ class Hello
* @CQCommand(pattern="*从*到*的随机数") * @CQCommand(pattern="*从*到*的随机数")
* @return string * @return string
*/ */
public function randNum() { public function randNum()
{
// 获取第一个数字类型的参数 // 获取第一个数字类型的参数
$num1 = ctx()->getNumArg("请输入第一个数字"); $num1 = ctx()->getNumArg('请输入第一个数字');
// 获取第二个数字类型的参数 // 获取第二个数字类型的参数
$num2 = ctx()->getNumArg("请输入第二个数字"); $num2 = ctx()->getNumArg('请输入第二个数字');
$a = min(intval($num1), intval($num2)); $a = min(intval($num1), intval($num2));
$b = max(intval($num1), intval($num2)); $b = max(intval($num1), intval($num2));
// 回复用户结果 // 回复用户结果
return "随机数是:" . mt_rand($a, $b); return '随机数是:' . mt_rand($a, $b);
} }
/** /**
@@ -139,8 +152,9 @@ class Hello
* @RequestMapping("/httpTimer") * @RequestMapping("/httpTimer")
* @Middleware("timer") * @Middleware("timer")
*/ */
public function timer() { public function timer()
return "This page is used as testing TimerMiddleware! Do not use it in production."; {
return 'This page is used as testing TimerMiddleware! Do not use it in production.';
} }
/** /**
@@ -148,8 +162,9 @@ class Hello
* @RequestMapping("/index") * @RequestMapping("/index")
* @RequestMapping("/") * @RequestMapping("/")
*/ */
public function index() { public function index()
return "Hello Zhamao!"; {
return 'Hello Zhamao!';
} }
/** /**
@@ -158,8 +173,9 @@ class Hello
* @param $param * @param $param
* @return string * @return string
*/ */
public function paramGet($param) { public function paramGet($param)
return "Hello, " . $param["name"]; {
return 'Hello, ' . $param['name'];
} }
/** /**
@@ -167,17 +183,18 @@ class Hello
* @OnOpenEvent("qq") * @OnOpenEvent("qq")
* @param $conn * @param $conn
*/ */
public function onConnect(ConnectionObject $conn) { public function onConnect(ConnectionObject $conn)
Console::info("机器人 " . $conn->getOption("connect_id") . " 已连接!"); {
Console::info('机器人 ' . $conn->getOption('connect_id') . ' 已连接!');
} }
/** /**
* 在机器人断开连接后向终端输出信息 * 在机器人断开连接后向终端输出信息
* @OnCloseEvent("qq") * @OnCloseEvent("qq")
* @param ConnectionObject $conn
*/ */
public function onDisconnect(ConnectionObject $conn) { public function onDisconnect(ConnectionObject $conn)
Console::info("机器人 " . $conn->getOption("connect_id") . " 已断开连接!"); {
Console::info('机器人 ' . $conn->getOption('connect_id') . ' 已断开连接!');
} }
/** /**
@@ -185,7 +202,8 @@ class Hello
* @OnRequestEvent(rule="ctx()->getRequest()->server['request_uri'] == '/favicon.ico'",level=200) * @OnRequestEvent(rule="ctx()->getRequest()->server['request_uri'] == '/favicon.ico'",level=200)
* @throws InterruptException * @throws InterruptException
*/ */
public function onRequest() { public function onRequest()
{
EventDispatcher::interrupt(); EventDispatcher::interrupt();
} }
@@ -193,8 +211,9 @@ class Hello
* 框架会默认关闭未知的WebSocket链接因为这个绑定的事件你可以根据你自己的需求进行修改 * 框架会默认关闭未知的WebSocket链接因为这个绑定的事件你可以根据你自己的需求进行修改
* @OnOpenEvent("default") * @OnOpenEvent("default")
*/ */
public function closeUnknownConn() { public function closeUnknownConn()
Console::info("Unknown connection , I will close it."); {
Console::info('Unknown connection , I will close it.');
server()->disconnect(ctx()->getConnection()->getFd()); server()->disconnect(ctx()->getConnection()->getFd());
} }
} }

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Module\Middleware; namespace Module\Middleware;
use Exception; use Exception;
@@ -13,7 +15,6 @@ use ZM\Http\MiddlewareInterface;
/** /**
* Class TimerMiddleware * Class TimerMiddleware
* 示例中间件:用于统计路由函数运行时间用的 * 示例中间件:用于统计路由函数运行时间用的
* @package Module\Middleware
* @MiddlewareClass("timer") * @MiddlewareClass("timer")
*/ */
class TimerMiddleware implements MiddlewareInterface class TimerMiddleware implements MiddlewareInterface
@@ -22,9 +23,9 @@ class TimerMiddleware implements MiddlewareInterface
/** /**
* @HandleBefore() * @HandleBefore()
* @return bool
*/ */
public function onBefore(): bool { public function onBefore(): bool
{
$this->starttime = microtime(true); $this->starttime = microtime(true);
return true; return true;
} }
@@ -32,17 +33,18 @@ class TimerMiddleware implements MiddlewareInterface
/** /**
* @HandleAfter() * @HandleAfter()
*/ */
public function onAfter() { public function onAfter()
Console::info("Using " . round((microtime(true) - $this->starttime) * 1000, 3) . " ms."); {
Console::info('Using ' . round((microtime(true) - $this->starttime) * 1000, 3) . ' ms.');
} }
/** /**
* @HandleException(\Exception::class) * @HandleException(\Exception::class)
* @param Exception $e
* @throws Exception * @throws Exception
*/ */
public function onException(Exception $e) { public function onException(Exception $e)
Console::error("Using " . round((microtime(true) - $this->starttime) * 1000, 3) . " ms but an Exception occurred."); {
Console::error('Using ' . round((microtime(true) - $this->starttime) * 1000, 3) . ' ms but an Exception occurred.');
throw $e; throw $e;
} }
} }

View File

@@ -1,11 +1,9 @@
<?php /** @noinspection PhpUnused */ <?php
/** @noinspection PhpMissingReturnTypeInspection */
declare(strict_types=1);
namespace ZM\API; namespace ZM\API;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Entity\CQObject; use ZM\Entity\CQObject;
@@ -16,12 +14,13 @@ class CQ
* @param $qq * @param $qq
* @return string * @return string
*/ */
public static function at($qq) { public static function at($qq)
if (is_numeric($qq) || $qq === "all") { {
return "[CQ:at,qq=" . $qq . "]"; if (is_numeric($qq) || $qq === 'all') {
return '[CQ:at,qq=' . $qq . ']';
} }
Console::warning(zm_internal_errcode("E00035") . "传入的QQ号码($qq)错误!"); Console::warning(zm_internal_errcode('E00035') . "传入的QQ号码({$qq})错误!");
return " "; return ' ';
} }
/** /**
@@ -29,127 +28,130 @@ class CQ
* @param $id * @param $id
* @return string * @return string
*/ */
public static function face($id) { public static function face($id)
{
if (is_numeric($id)) { if (is_numeric($id)) {
return "[CQ:face,id=" . $id . "]"; return '[CQ:face,id=' . $id . ']';
} }
Console::warning(zm_internal_errcode("E00035") . "传入的face id($id)错误!"); Console::warning(zm_internal_errcode('E00035') . "传入的face id({$id})错误!");
return " "; return ' ';
} }
/** /**
* 发送图片 * 发送图片
* @param $file * @param $file
* @param bool $cache
* @param bool $flash
* @param bool $proxy
* @param int $timeout
* @return string * @return string
*/ */
public static function image($file, bool $cache = true, bool $flash = false, bool $proxy = true, int $timeout = -1) { public static function image($file, bool $cache = true, bool $flash = false, bool $proxy = true, int $timeout = -1)
{
return return
"[CQ:image,file=" . self::encode($file, true) . '[CQ:image,file=' . self::encode($file, true) .
(!$cache ? ",cache=0" : "") . (!$cache ? ',cache=0' : '') .
($flash ? ",type=flash" : "") . ($flash ? ',type=flash' : '') .
(!$proxy ? ",proxy=false" : "") . (!$proxy ? ',proxy=false' : '') .
($timeout != -1 ? (",timeout=" . $timeout) : "") . ($timeout != -1 ? (',timeout=' . $timeout) : '') .
"]"; ']';
} }
/** /**
* 发送语音 * 发送语音
* @param $file * @param $file
* @param bool $magic
* @param bool $cache
* @param bool $proxy
* @param int $timeout
* @return string * @return string
*/ */
public static function record($file, bool $magic = false, bool $cache = true, bool $proxy = true, int $timeout = -1) { public static function record($file, bool $magic = false, bool $cache = true, bool $proxy = true, int $timeout = -1)
{
return return
"[CQ:record,file=" . self::encode($file, true) . '[CQ:record,file=' . self::encode($file, true) .
(!$cache ? ",cache=0" : "") . (!$cache ? ',cache=0' : '') .
($magic ? ",magic=1" : "") . ($magic ? ',magic=1' : '') .
(!$proxy ? ",proxy=false" : "") . (!$proxy ? ',proxy=false' : '') .
($timeout != -1 ? (",timeout=" . $timeout) : "") . ($timeout != -1 ? (',timeout=' . $timeout) : '') .
"]"; ']';
} }
/** /**
* 发送短视频 * 发送短视频
* @param $file * @param $file
* @param bool $cache
* @param bool $proxy
* @param int $timeout
* @return string * @return string
*/ */
public static function video($file, bool $cache = true, bool $proxy = true, int $timeout = -1) { public static function video($file, bool $cache = true, bool $proxy = true, int $timeout = -1)
{
return return
"[CQ:video,file=" . self::encode($file, true) . '[CQ:video,file=' . self::encode($file, true) .
(!$cache ? ",cache=0" : "") . (!$cache ? ',cache=0' : '') .
(!$proxy ? ",proxy=false" : "") . (!$proxy ? ',proxy=false' : '') .
($timeout != -1 ? (",timeout=" . intval($timeout)) : "") . ($timeout != -1 ? (',timeout=' . $timeout) : '') .
"]"; ']';
} }
/** /**
* 发送投掷骰子(只能在单条回复中单独使用) * 发送投掷骰子(只能在单条回复中单独使用)
* @return string * @return string
*/ */
public static function rps() { public static function rps()
return "[CQ:rps]"; {
return '[CQ:rps]';
} }
/** /**
* 发送掷骰子表情(只能在单条回复中单独使用) * 发送掷骰子表情(只能在单条回复中单独使用)
* @return string * @return string
*/ */
public static function dice() { public static function dice()
return "[CQ:dice]"; {
return '[CQ:dice]';
} }
/** /**
* 戳一戳(原窗口抖动,仅支持好友消息使用) * 戳一戳(原窗口抖动,仅支持好友消息使用)
* @return string * @return string
*/ */
public static function shake() { public static function shake()
return "[CQ:shake]"; {
return '[CQ:shake]';
} }
/** /**
* 发送新的戳一戳 * 发送新的戳一戳
* @param $type * @param $type
* @param $id * @param $id
* @param string $name
* @return string * @return string
*/ */
public static function poke($type, $id, string $name = "") { public static function poke($type, $id, string $name = '')
return "[CQ:poke,type=$type,id=$id" . ($name != "" ? (",name=" . self::encode($name, true)) : "") . "]"; {
return "[CQ:poke,type={$type},id={$id}" . ($name != '' ? (',name=' . self::encode($name, true)) : '') . ']';
} }
/** /**
* 发送匿名消息 * 发送匿名消息
* @param int $ignore
* @return string * @return string
*/ */
public static function anonymous(int $ignore = 1) { public static function anonymous(int $ignore = 1)
return "[CQ:anonymous" . ($ignore != 1 ? ",ignore=0" : "") . "]"; {
return '[CQ:anonymous' . ($ignore != 1 ? ',ignore=0' : '') . ']';
} }
/** /**
* 发送链接分享(只能在单条回复中单独使用) * 发送链接分享(只能在单条回复中单独使用)
* @param $url * @param $url
* @param $title * @param $title
* @param null $content * @param null $content
* @param null $image * @param null $image
* @return string * @return string
*/ */
public static function share($url, $title, $content = null, $image = null) { public static function share($url, $title, $content = null, $image = null)
if ($content === null) $c = ""; {
else $c = ",content=" . self::encode($content, true); if ($content === null) {
if ($image === null) $i = ""; $c = '';
else $i = ",image=" . self::encode($image, true); } else {
return "[CQ:share,url=" . self::encode($url, true) . ",title=" . self::encode($title, true) . $c . $i . "]"; $c = ',content=' . self::encode($content, true);
}
if ($image === null) {
$i = '';
} else {
$i = ',image=' . self::encode($image, true);
}
return '[CQ:share,url=' . self::encode($url, true) . ',title=' . self::encode($title, true) . $c . $i . ']';
} }
/** /**
@@ -158,25 +160,25 @@ class CQ
* @param $id * @param $id
* @return string * @return string
*/ */
public static function contact($type, $id) { public static function contact($type, $id)
return "[CQ:contact,type=$type,id=$id]"; {
return "[CQ:contact,type={$type},id={$id}]";
} }
/** /**
* 发送位置 * 发送位置
* @param $lat * @param $lat
* @param $lon * @param $lon
* @param string $title
* @param string $content
* @return string * @return string
*/ */
public static function location($lat, $lon, string $title = "", string $content = "") { public static function location($lat, $lon, string $title = '', string $content = '')
return "[CQ:location" . {
",lat=" . self::encode($lat, true) . return '[CQ:location' .
",lon=" . self::encode($lon, true) . ',lat=' . self::encode($lat, true) .
($title != "" ? (",title=" . self::encode($title, true)) : "") . ',lon=' . self::encode($lon, true) .
($content != "" ? (",content=" . self::encode($content, true)) : "") . ($title != '' ? (',title=' . self::encode($title, true)) : '') .
"]"; ($content != '' ? (',content=' . self::encode($content, true)) : '') .
']';
} }
/** /**
@@ -191,101 +193,119 @@ class CQ
* $image 为音乐卡片的图片链接地址(可忽略) * $image 为音乐卡片的图片链接地址(可忽略)
* @param $type * @param $type
* @param $id_or_url * @param $id_or_url
* @param null $audio * @param null $audio
* @param null $title * @param null $title
* @param null $content * @param null $content
* @param null $image * @param null $image
* @return string * @return string
*/ */
public static function music($type, $id_or_url, $audio = null, $title = null, $content = null, $image = null) { public static function music($type, $id_or_url, $audio = null, $title = null, $content = null, $image = null)
{
switch ($type) { switch ($type) {
case "qq": case 'qq':
case "163": case '163':
case "xiami": case 'xiami':
return "[CQ:music,type=$type,id=$id_or_url]"; return "[CQ:music,type={$type},id={$id_or_url}]";
case "custom": case 'custom':
if ($title === null || $audio === null) { if ($title === null || $audio === null) {
Console::warning(zm_internal_errcode("E00035") . "传入CQ码实例的标题和音频链接不能为空"); Console::warning(zm_internal_errcode('E00035') . '传入CQ码实例的标题和音频链接不能为空');
return " "; return ' ';
} }
if ($content === null) $c = ""; if ($content === null) {
else $c = ",content=" . self::encode($content, true); $c = '';
if ($image === null) $i = ""; } else {
else $i = ",image=" . self::encode($image, true); $c = ',content=' . self::encode($content, true);
return "[CQ:music,type=custom,url=" . }
if ($image === null) {
$i = '';
} else {
$i = ',image=' . self::encode($image, true);
}
return '[CQ:music,type=custom,url=' .
self::encode($id_or_url, true) . self::encode($id_or_url, true) .
",audio=" . self::encode($audio, true) . ",title=" . self::encode($title, true) . $c . $i . ',audio=' . self::encode($audio, true) . ',title=' . self::encode($title, true) . $c . $i .
"]"; ']';
default: default:
Console::warning(zm_internal_errcode("E00035") . "传入的music type($type)错误!"); Console::warning(zm_internal_errcode('E00035') . "传入的music type({$type})错误!");
return " "; return ' ';
} }
} }
public static function forward($id) { public static function forward($id)
return "[CQ:forward,id=".self::encode($id)."]"; {
return '[CQ:forward,id=' . self::encode($id) . ']';
} }
public static function node($user_id, $nickname, $content) { public static function node($user_id, $nickname, $content)
return "[CQ:node,user_id=$user_id,nickname=" . self::encode($nickname, true) . ",content=" . self::encode($content, true) . "]"; {
return "[CQ:node,user_id={$user_id},nickname=" . self::encode($nickname, true) . ',content=' . self::encode($content, true) . ']';
} }
public static function xml($data) { public static function xml($data)
return "[CQ:xml,data=" . self::encode($data, true) . "]"; {
return '[CQ:xml,data=' . self::encode($data, true) . ']';
} }
public static function json($data, $resid = 0) { public static function json($data, $resid = 0)
return "[CQ:json,data=" . self::encode($data, true) . ",resid=" . intval($resid) . "]"; {
return '[CQ:json,data=' . self::encode($data, true) . ',resid=' . intval($resid) . ']';
} }
public static function _custom(string $type_name, $params) { public static function _custom(string $type_name, $params)
$code = "[CQ:" . $type_name; {
$code = '[CQ:' . $type_name;
foreach ($params as $k => $v) { foreach ($params as $k => $v) {
$code .= "," . $k . "=" . self::escape($v, true); $code .= ',' . $k . '=' . self::escape($v, true);
} }
$code .= "]"; $code .= ']';
return $code; return $code;
} }
/** /**
* 反转义字符串中的CQ码敏感符号 * 反转义字符串中的CQ码敏感符号
* @param $msg * @param mixed $msg
* @param bool $is_content * @param mixed $is_content
* @return mixed
*/ */
public static function decode($msg, $is_content = false) { public static function decode($msg, $is_content = false)
$msg = str_replace(["&amp;", "&#91;", "&#93;"], ["&", "[", "]"], $msg); {
if ($is_content) $msg = str_replace("&#44;", ",", $msg); $msg = str_replace(['&amp;', '&#91;', '&#93;'], ['&', '[', ']'], $msg);
if ($is_content) {
$msg = str_replace('&#44;', ',', $msg);
}
return $msg; return $msg;
} }
public static function replace($str) { public static function replace($str)
$str = str_replace("{{", "[", $str); {
$str = str_replace("}}", "]", $str); $str = str_replace('{{', '[', $str);
return $str; return str_replace('}}', ']', $str);
} }
/** /**
* 转义CQ码的特殊字符同encode * 转义CQ码的特殊字符同encode
* @param $msg * @param mixed $msg
* @param bool $is_content * @param mixed $is_content
* @return mixed
*/ */
public static function escape($msg, $is_content = false) { public static function escape($msg, $is_content = false)
$msg = str_replace(["&", "[", "]"], ["&amp;", "&#91;", "&#93;"], $msg); {
if ($is_content) $msg = str_replace(",", "&#44;", $msg); $msg = str_replace(['&', '[', ']'], ['&amp;', '&#91;', '&#93;'], $msg);
if ($is_content) {
$msg = str_replace(',', '&#44;', $msg);
}
return $msg; return $msg;
} }
/** /**
* 转义CQ码的特殊字符 * 转义CQ码的特殊字符
* @param $msg * @param mixed $msg
* @param false $is_content * @param mixed $is_content
* @return mixed
*/ */
public static function encode($msg, $is_content = false) { public static function encode($msg, $is_content = false)
$msg = str_replace(["&", "[", "]"], ["&amp;", "&#91;", "&#93;"], $msg); {
if ($is_content) $msg = str_replace(",", "&#44;", $msg); $msg = str_replace(['&', '[', ']'], ['&amp;', '&#91;', '&#93;'], $msg);
if ($is_content) {
$msg = str_replace(',', '&#44;', $msg);
}
return $msg; return $msg;
} }
@@ -294,12 +314,13 @@ class CQ
* @param $msg * @param $msg
* @return string * @return string
*/ */
public static function removeCQ($msg) { public static function removeCQ($msg)
$final = ""; {
$final = '';
$last_end = 0; $last_end = 0;
foreach (self::getAllCQ($msg) as $v) { foreach (self::getAllCQ($msg) as $v) {
$final .= mb_substr($msg, $last_end, $v["start"] - $last_end); $final .= mb_substr($msg, $last_end, $v['start'] - $last_end);
$last_end = $v["end"] + 1; $last_end = $v['end'] + 1;
} }
$final .= mb_substr($msg, $last_end); $final .= mb_substr($msg, $last_end);
return $final; return $final;
@@ -307,55 +328,58 @@ class CQ
/** /**
* 获取消息中第一个CQ码 * 获取消息中第一个CQ码
* @param $msg * @param mixed $msg
* @param bool $is_object * @param mixed $is_object
* @return array|CQObject|null
*/ */
public static function getCQ($msg, $is_object = false) { public static function getCQ($msg, $is_object = false)
if (($head = mb_strpos($msg, "[CQ:")) !== false) { {
if (($head = mb_strpos($msg, '[CQ:')) !== false) {
$key_offset = mb_substr($msg, $head); $key_offset = mb_substr($msg, $head);
$close = mb_strpos($key_offset, "]"); $close = mb_strpos($key_offset, ']');
if ($close === false) return null; if ($close === false) {
$content = mb_substr($msg, $head + 4, $close + $head - mb_strlen($msg)); return null;
$exp = explode(",", $content);
$cq["type"] = array_shift($exp);
foreach ($exp as $v) {
$ss = explode("=", $v);
$sk = array_shift($ss);
$cq["params"][$sk] = self::decode(implode("=", $ss), true);
} }
$cq["start"] = $head; $content = mb_substr($msg, $head + 4, $close + $head - mb_strlen($msg));
$cq["end"] = $close + $head; $exp = explode(',', $content);
$cq['type'] = array_shift($exp);
foreach ($exp as $v) {
$ss = explode('=', $v);
$sk = array_shift($ss);
$cq['params'][$sk] = self::decode(implode('=', $ss), true);
}
$cq['start'] = $head;
$cq['end'] = $close + $head;
return !$is_object ? $cq : CQObject::fromArray($cq); return !$is_object ? $cq : CQObject::fromArray($cq);
} else {
return null;
} }
return null;
} }
/** /**
* 获取消息中所有的CQ码 * 获取消息中所有的CQ码
* @param $msg * @param mixed $msg
* @param bool $is_object * @param mixed $is_object
* @return array|CQObject[]
*/ */
public static function getAllCQ($msg, $is_object = false) { public static function getAllCQ($msg, $is_object = false)
{
$cqs = []; $cqs = [];
$offset = 0; $offset = 0;
while (($head = mb_strpos(($submsg = mb_substr($msg, $offset)), "[CQ:")) !== false) { while (($head = mb_strpos(($submsg = mb_substr($msg, $offset)), '[CQ:')) !== false) {
$key_offset = mb_substr($submsg, $head); $key_offset = mb_substr($submsg, $head);
$tmpmsg = mb_strpos($key_offset, "]"); $tmpmsg = mb_strpos($key_offset, ']');
if ($tmpmsg === false) break; // 没闭合不算CQ码 if ($tmpmsg === false) {
break;
} // 没闭合不算CQ码
$content = mb_substr($submsg, $head + 4, $tmpmsg + $head - mb_strlen($submsg)); $content = mb_substr($submsg, $head + 4, $tmpmsg + $head - mb_strlen($submsg));
$exp = explode(",", $content); $exp = explode(',', $content);
$cq = []; $cq = [];
$cq["type"] = array_shift($exp); $cq['type'] = array_shift($exp);
foreach ($exp as $v) { foreach ($exp as $v) {
$ss = explode("=", $v); $ss = explode('=', $v);
$sk = array_shift($ss); $sk = array_shift($ss);
$cq["params"][$sk] = self::decode(implode("=", $ss), true); $cq['params'][$sk] = self::decode(implode('=', $ss), true);
} }
$cq["start"] = $offset + $head; $cq['start'] = $offset + $head;
$cq["end"] = $offset + $tmpmsg + $head; $cq['end'] = $offset + $tmpmsg + $head;
$offset += $head + $tmpmsg + 1; $offset += $head + $tmpmsg + 1;
$cqs[] = (!$is_object ? $cq : CQObject::fromArray($cq)); $cqs[] = (!$is_object ? $cq : CQObject::fromArray($cq));
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\API; namespace ZM\API;
@@ -13,80 +14,89 @@ use ZM\Utils\CoMessage;
trait CQAPI trait CQAPI
{ {
/** @var null|Closure */ /** @var null|Closure */
private static $filter = null; private static $filter;
public static function registerFilter(callable $callable) { public function __call($name, $arguments)
{
return false;
}
public static function registerFilter(callable $callable)
{
self::$filter = $callable; self::$filter = $callable;
} }
public function getActionName($suffix, string $method)
{
$postfix = ($suffix == OneBotV11::API_ASYNC ? '_async' : ($suffix == OneBotV11::API_RATE_LIMITED ? '_rate_limited' : ''));
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
return $func_name . $postfix;
}
/** /**
* @param $connection * @param $connection
* @param $reply * @param $reply
* @param |null $function * @param |null $function
* @return bool|array * @return array|bool
*/ */
private function processAPI($connection, $reply, $function = null) { private function processAPI($connection, $reply, $function = null)
{
if (is_callable(self::$filter)) { if (is_callable(self::$filter)) {
$reply2 = call_user_func(self::$filter, $reply); $reply2 = call_user_func(self::$filter, $reply);
if (is_bool($reply2)) return $reply2; if (is_bool($reply2)) {
else $reply = $reply2; return $reply2;
}
$reply = $reply2;
} }
if ($connection->getOption("type") === CONN_WEBSOCKET) if ($connection->getOption('type') === CONN_WEBSOCKET) {
return $this->processWebsocketAPI($connection, $reply, $function); return $this->processWebsocketAPI($connection, $reply, $function);
else }
return $this->processHttpAPI($connection, $reply, $function);
return $this->processHttpAPI($connection, $reply, $function);
} }
private function processWebsocketAPI($connection, $reply, $function = false) { private function processWebsocketAPI($connection, $reply, $function = false)
$api_id = ZMAtomic::get("wait_msg_id")->add(1); {
$reply["echo"] = $api_id; $api_id = ZMAtomic::get('wait_msg_id')->add(1);
$reply['echo'] = $api_id;
if (server()->push($connection->getFd(), json_encode($reply))) { if (server()->push($connection->getFd(), json_encode($reply))) {
if ($function === true) { if ($function === true) {
$obj = [ $obj = [
"data" => $reply, 'data' => $reply,
"time" => microtime(true), 'time' => microtime(true),
"self_id" => $connection->getOption("connect_id"), 'self_id' => $connection->getOption('connect_id'),
"echo" => $api_id 'echo' => $api_id,
]; ];
return CoMessage::yieldByWS($obj, ["echo"], 30); return CoMessage::yieldByWS($obj, ['echo'], 30);
} }
return true; return true;
} else {
Console::warning(zm_internal_errcode("E00036") . "CQAPI send failed, websocket push error.");
$response = [
"status" => "failed",
"retcode" => -1000,
"data" => null,
"self_id" => $connection->getOption("connect_id")
];
SpinLock::lock("wait_api");
$r = LightCacheInside::get("wait_api", "wait_api");
unset($r[$reply["echo"]]);
LightCacheInside::set("wait_api", "wait_api", $r);
SpinLock::unlock("wait_api");
if ($function === true) return $response;
return false;
} }
Console::warning(zm_internal_errcode('E00036') . 'CQAPI send failed, websocket push error.');
$response = [
'status' => 'failed',
'retcode' => -1000,
'data' => null,
'self_id' => $connection->getOption('connect_id'),
];
SpinLock::lock('wait_api');
$r = LightCacheInside::get('wait_api', 'wait_api');
unset($r[$reply['echo']]);
LightCacheInside::set('wait_api', 'wait_api', $r);
SpinLock::unlock('wait_api');
if ($function === true) {
return $response;
}
return false;
} }
/** /**
* @param $connection * @param $connection
* @param $reply * @param $reply
* @param null $function * @param null $function
* @return bool
* @noinspection PhpUnusedParameterInspection * @noinspection PhpUnusedParameterInspection
*/ */
private function processHttpAPI($connection, $reply, $function = null): bool { private function processHttpAPI($connection, $reply, $function = null): bool
return false; {
}
public function getActionName($suffix, string $method) {
$postfix = ($suffix == OneBotV11::API_ASYNC ? '_async' : ($suffix == OneBotV11::API_RATE_LIMITED ? '_rate_limited' : ''));
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
return $func_name . $postfix;
}
public function __call($name, $arguments) {
return false; return false;
} }
} }

View File

@@ -1,15 +1,19 @@
<?php <?php
declare(strict_types=1);
namespace ZM\API; namespace ZM\API;
class GoCqhttpAPIV11 class GoCqhttpAPIV11
{ {
const SUPPORT_VERSION = '1.0.0-beta8';
use CQAPI; use CQAPI;
public const SUPPORT_VERSION = '1.0.0-beta8';
private $connection; private $connection;
private $callback; private $callback;
private $prefix; private $prefix;
public function __construct($connection, $callback, $prefix) public function __construct($connection, $callback, $prefix)
@@ -22,90 +26,95 @@ class GoCqhttpAPIV11
/** /**
* 获取频道系统内BOT的资料 * 获取频道系统内BOT的资料
* 响应字段nickname, tiny_id, avatar_url * 响应字段nickname, tiny_id, avatar_url
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E7%B3%BB%E7%BB%9F%E5%86%85bot%E7%9A%84%E8%B5%84%E6%96%99 * @see https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E7%B3%BB%E7%BB%9F%E5%86%85bot%E7%9A%84%E8%B5%84%E6%96%99
* @return array|bool * @return array|bool
*/ */
public function getGuildServiceProfile() public function getGuildServiceProfile()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取频道列表 * 获取频道列表
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8 * @see https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8
* @return array|bool * @return array|bool
*/ */
public function getGuildList() { public function getGuildList()
{
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 通过访客获取频道元数据 * 通过访客获取频道元数据
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E9%80%9A%E8%BF%87%E8%AE%BF%E5%AE%A2%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E5%85%83%E6%95%B0%E6%8D%AE * @see https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E9%80%9A%E8%BF%87%E8%AE%BF%E5%AE%A2%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E5%85%83%E6%95%B0%E6%8D%AE
* @param $guild_id * @param $guild_id
* @return array|bool * @return array|bool
*/ */
public function getGuildMetaByGuest($guild_id) { public function getGuildMetaByGuest($guild_id)
{
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'guild_id' => $guild_id 'guild_id' => $guild_id,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取子频道列表 * 获取子频道列表
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E5%AD%90%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8 * @see https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E5%AD%90%E9%A2%91%E9%81%93%E5%88%97%E8%A1%A8
* @param $guild_id * @param $guild_id
* @param false $no_cache * @param false $no_cache
* @return array|bool * @return array|bool
*/ */
public function getGuildChannelList($guild_id, bool $no_cache = false) { public function getGuildChannelList($guild_id, bool $no_cache = false)
{
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'guild_id' => $guild_id, 'guild_id' => $guild_id,
'no_cache' => $no_cache 'no_cache' => $no_cache,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取频道成员列表 * 获取频道成员列表
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E6%88%90%E5%91%98%E5%88%97%E8%A1%A8 * @see https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E8%8E%B7%E5%8F%96%E9%A2%91%E9%81%93%E6%88%90%E5%91%98%E5%88%97%E8%A1%A8
* @param $guild_id * @param $guild_id
* @return array|bool * @return array|bool
*/ */
public function getGuildMembers($guild_id) { public function getGuildMembers($guild_id)
{
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'guild_id' => $guild_id 'guild_id' => $guild_id,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 发送信息到子频道 * 发送信息到子频道
* @link https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E5%8F%91%E9%80%81%E4%BF%A1%E6%81%AF%E5%88%B0%E5%AD%90%E9%A2%91%E9%81%93 * @see https://github.com/Mrs4s/go-cqhttp/blob/master/docs/guild.md#%E5%8F%91%E9%80%81%E4%BF%A1%E6%81%AF%E5%88%B0%E5%AD%90%E9%A2%91%E9%81%93
* @param $guild_id * @param $guild_id
* @param $channel_id * @param $channel_id
* @param $message * @param $message
* @return array|bool * @return array|bool
*/ */
public function sendGuildChannelMsg($guild_id, $channel_id, $message) { public function sendGuildChannelMsg($guild_id, $channel_id, $message)
{
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'guild_id' => $guild_id, 'guild_id' => $guild_id,
'channel_id' => $channel_id, 'channel_id' => $channel_id,
'message' => $message 'message' => $message,
] ],
], $this->callback); ], $this->callback);
} }
} }

View File

@@ -1,5 +1,8 @@
<?php /** @noinspection PhpUnused */ <?php
/** @noinspection PhpUnused */
declare(strict_types=1);
namespace ZM\API; namespace ZM\API;
@@ -11,45 +14,56 @@ use ZM\Exception\ZMKnownException;
/** /**
* OneBot V11 的 API 实现类 * OneBot V11 的 API 实现类
* Class OneBotV11 * Class OneBotV11
* @package ZM\API * @since 2.5.0
* @since 2.5
*/ */
class OneBotV11 class OneBotV11
{ {
use CQAPI; use CQAPI;
const API_ASYNC = 1; public const API_ASYNC = 1;
const API_NORMAL = 0;
const API_RATE_LIMITED = 2;
/** @var ConnectionObject|null */ public const API_NORMAL = 0;
public const API_RATE_LIMITED = 2;
/** @var null|ConnectionObject */
protected $connection; protected $connection;
protected $callback = true; protected $callback = true;
protected $prefix = 0; protected $prefix = 0;
public function __construct(ConnectionObject $connection)
{
$this->connection = $connection;
}
/** /**
* @param $robot_id * @param $robot_id
* @return ZMRobot
* @throws RobotNotFoundException * @throws RobotNotFoundException
* @return ZMRobot
*/ */
public static function get($robot_id) public static function get($robot_id)
{ {
$r = ManagerGM::getAllByName('qq'); $r = ManagerGM::getAllByName('qq');
foreach ($r as $v) { foreach ($r as $v) {
if ($v->getOption('connect_id') == $robot_id) return new ZMRobot($v); if ($v->getOption('connect_id') == $robot_id) {
return new ZMRobot($v);
}
} }
throw new RobotNotFoundException("机器人 " . $robot_id . " 未连接到框架!"); throw new RobotNotFoundException('机器人 ' . $robot_id . ' 未连接到框架!');
} }
/** /**
* @return ZMRobot
* @throws RobotNotFoundException * @throws RobotNotFoundException
* @return ZMRobot
*/ */
public static function getRandom() public static function getRandom()
{ {
$r = ManagerGM::getAllByName('qq'); $r = ManagerGM::getAllByName('qq');
if ($r == []) throw new RobotNotFoundException("没有任何机器人连接到框架!"); if ($r == []) {
throw new RobotNotFoundException('没有任何机器人连接到框架!');
}
return new ZMRobot($r[array_rand($r)]); return new ZMRobot($r[array_rand($r)]);
} }
@@ -66,11 +80,6 @@ class OneBotV11
return $obj; return $obj;
} }
public function __construct(ConnectionObject $connection)
{
$this->connection = $connection;
}
public function setCallback($callback = true) public function setCallback($callback = true)
{ {
$this->callback = $callback; $this->callback = $callback;
@@ -92,11 +101,10 @@ class OneBotV11
/** /**
* 发送私聊消息 * 发送私聊消息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_private_msg-%E5%8F%91%E9%80%81%E7%A7%81%E8%81%8A%E6%B6%88%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_private_msg-%E5%8F%91%E9%80%81%E7%A7%81%E8%81%8A%E6%B6%88%E6%81%AF
* @param $user_id * @param $user_id
* @param $message * @param $message
* @param bool $auto_escape * @return null|array|bool
* @return array|bool|null
*/ */
public function sendPrivateMsg($user_id, $message, bool $auto_escape = false) public function sendPrivateMsg($user_id, $message, bool $auto_escape = false)
{ {
@@ -105,18 +113,17 @@ class OneBotV11
'params' => [ 'params' => [
'user_id' => $user_id, 'user_id' => $user_id,
'message' => $message, 'message' => $message,
'auto_escape' => $auto_escape 'auto_escape' => $auto_escape,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 发送群消息 * 发送群消息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_group_msg-%E5%8F%91%E9%80%81%E7%BE%A4%E6%B6%88%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_group_msg-%E5%8F%91%E9%80%81%E7%BE%A4%E6%B6%88%E6%81%AF
* @param $group_id * @param $group_id
* @param $message * @param $message
* @param bool $auto_escape * @return null|array|bool
* @return array|bool|null
*/ */
public function sendGroupMsg($group_id, $message, bool $auto_escape = false) public function sendGroupMsg($group_id, $message, bool $auto_escape = false)
{ {
@@ -125,19 +132,18 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'message' => $message, 'message' => $message,
'auto_escape' => $auto_escape 'auto_escape' => $auto_escape,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 发送消息 * 发送消息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_msg-%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_msg-%E5%8F%91%E9%80%81%E6%B6%88%E6%81%AF
* @param $message_type * @param $message_type
* @param $target_id * @param $target_id
* @param $message * @param $message
* @param bool $auto_escape * @return null|array|bool
* @return array|bool|null
*/ */
public function sendMsg($message_type, $target_id, $message, bool $auto_escape = false) public function sendMsg($message_type, $target_id, $message, bool $auto_escape = false)
{ {
@@ -147,65 +153,64 @@ class OneBotV11
'message_type' => $message_type, 'message_type' => $message_type,
($message_type == 'private' ? 'user' : $message_type) . '_id' => $target_id, ($message_type == 'private' ? 'user' : $message_type) . '_id' => $target_id,
'message' => $message, 'message' => $message,
'auto_escape' => $auto_escape 'auto_escape' => $auto_escape,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 撤回消息 * 撤回消息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#delete_msg-%E6%92%A4%E5%9B%9E%E6%B6%88%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#delete_msg-%E6%92%A4%E5%9B%9E%E6%B6%88%E6%81%AF
* @param $message_id * @param $message_id
* @return array|bool|null * @return null|array|bool
*/ */
public function deleteMsg($message_id) public function deleteMsg($message_id)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'message_id' => $message_id 'message_id' => $message_id,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取消息 * 获取消息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_msg-%E8%8E%B7%E5%8F%96%E6%B6%88%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_msg-%E8%8E%B7%E5%8F%96%E6%B6%88%E6%81%AF
* @param $message_id * @param $message_id
* @return array|bool|null * @return null|array|bool
*/ */
public function getMsg($message_id) public function getMsg($message_id)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'message_id' => $message_id 'message_id' => $message_id,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取合并转发消息 * 获取合并转发消息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_forward_msg-%E8%8E%B7%E5%8F%96%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91%E6%B6%88%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_forward_msg-%E8%8E%B7%E5%8F%96%E5%90%88%E5%B9%B6%E8%BD%AC%E5%8F%91%E6%B6%88%E6%81%AF
* @param $id * @param $id
* @return array|bool|null * @return null|array|bool
*/ */
public function getForwardMsg($id) public function getForwardMsg($id)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'id' => $id 'id' => $id,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 发送好友赞 * 发送好友赞
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_like-%E5%8F%91%E9%80%81%E5%A5%BD%E5%8F%8B%E8%B5%9E * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#send_like-%E5%8F%91%E9%80%81%E5%A5%BD%E5%8F%8B%E8%B5%9E
* @param $user_id * @param $user_id
* @param int $times * @return null|array|bool
* @return array|bool|null
*/ */
public function sendLike($user_id, int $times = 1) public function sendLike($user_id, int $times = 1)
{ {
@@ -213,18 +218,17 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'user_id' => $user_id, 'user_id' => $user_id,
'times' => $times 'times' => $times,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 群组踢人 * 群组踢人
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_kick-%E7%BE%A4%E7%BB%84%E8%B8%A2%E4%BA%BA * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_kick-%E7%BE%A4%E7%BB%84%E8%B8%A2%E4%BA%BA
* @param $group_id * @param $group_id
* @param $user_id * @param $user_id
* @param bool $reject_add_request * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupKick($group_id, $user_id, bool $reject_add_request = false) public function setGroupKick($group_id, $user_id, bool $reject_add_request = false)
{ {
@@ -233,18 +237,17 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'user_id' => $user_id, 'user_id' => $user_id,
'reject_add_request' => $reject_add_request 'reject_add_request' => $reject_add_request,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 群组单人禁言 * 群组单人禁言
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_ban-%E7%BE%A4%E7%BB%84%E5%8D%95%E4%BA%BA%E7%A6%81%E8%A8%80 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_ban-%E7%BE%A4%E7%BB%84%E5%8D%95%E4%BA%BA%E7%A6%81%E8%A8%80
* @param $group_id * @param $group_id
* @param $user_id * @param $user_id
* @param int $duration * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupBan($group_id, $user_id, int $duration = 1800) public function setGroupBan($group_id, $user_id, int $duration = 1800)
{ {
@@ -253,18 +256,17 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'user_id' => $user_id, 'user_id' => $user_id,
'duration' => $duration 'duration' => $duration,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 群组匿名用户禁言 * 群组匿名用户禁言
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_anonymous_ban-%E7%BE%A4%E7%BB%84%E5%8C%BF%E5%90%8D%E7%94%A8%E6%88%B7%E7%A6%81%E8%A8%80 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_anonymous_ban-%E7%BE%A4%E7%BB%84%E5%8C%BF%E5%90%8D%E7%94%A8%E6%88%B7%E7%A6%81%E8%A8%80
* @param $group_id * @param $group_id
* @param $anonymous_or_flag * @param $anonymous_or_flag
* @param int $duration * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupAnonymousBan($group_id, $anonymous_or_flag, int $duration = 1800) public function setGroupAnonymousBan($group_id, $anonymous_or_flag, int $duration = 1800)
{ {
@@ -273,17 +275,16 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
(is_string($anonymous_or_flag) ? 'flag' : 'anonymous') => $anonymous_or_flag, (is_string($anonymous_or_flag) ? 'flag' : 'anonymous') => $anonymous_or_flag,
'duration' => $duration 'duration' => $duration,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 群组全员禁言 * 群组全员禁言
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_whole_ban-%E7%BE%A4%E7%BB%84%E5%85%A8%E5%91%98%E7%A6%81%E8%A8%80 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_whole_ban-%E7%BE%A4%E7%BB%84%E5%85%A8%E5%91%98%E7%A6%81%E8%A8%80
* @param $group_id * @param $group_id
* @param bool $enable * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupWholeBan($group_id, bool $enable = true) public function setGroupWholeBan($group_id, bool $enable = true)
{ {
@@ -291,18 +292,17 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'enable' => $enable 'enable' => $enable,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 群组设置管理员 * 群组设置管理员
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_admin-%E7%BE%A4%E7%BB%84%E8%AE%BE%E7%BD%AE%E7%AE%A1%E7%90%86%E5%91%98 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_admin-%E7%BE%A4%E7%BB%84%E8%AE%BE%E7%BD%AE%E7%AE%A1%E7%90%86%E5%91%98
* @param $group_id * @param $group_id
* @param $user_id * @param $user_id
* @param bool $enable * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupAdmin($group_id, $user_id, bool $enable = true) public function setGroupAdmin($group_id, $user_id, bool $enable = true)
{ {
@@ -311,17 +311,16 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'user_id' => $user_id, 'user_id' => $user_id,
'enable' => $enable 'enable' => $enable,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 群组匿名 * 群组匿名
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_anonymous-%E7%BE%A4%E7%BB%84%E5%8C%BF%E5%90%8D * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_anonymous-%E7%BE%A4%E7%BB%84%E5%8C%BF%E5%90%8D
* @param $group_id * @param $group_id
* @param bool $enable * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupAnonymous($group_id, bool $enable = true) public function setGroupAnonymous($group_id, bool $enable = true)
{ {
@@ -329,18 +328,17 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'enable' => $enable 'enable' => $enable,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 设置群名片(群备注) * 设置群名片(群备注)
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_card-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E5%90%8D%E7%89%87%E7%BE%A4%E5%A4%87%E6%B3%A8 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_card-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E5%90%8D%E7%89%87%E7%BE%A4%E5%A4%87%E6%B3%A8
* @param $group_id * @param $group_id
* @param $user_id * @param $user_id
* @param string $card * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupCard($group_id, $user_id, string $card = '') public function setGroupCard($group_id, $user_id, string $card = '')
{ {
@@ -349,17 +347,17 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'user_id' => $user_id, 'user_id' => $user_id,
'card' => $card 'card' => $card,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 设置群名 * 设置群名
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_name-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E5%90%8D * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_name-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E5%90%8D
* @param $group_id * @param $group_id
* @param $group_name * @param $group_name
* @return array|bool|null * @return null|array|bool
*/ */
public function setGroupName($group_id, $group_name) public function setGroupName($group_id, $group_name)
{ {
@@ -367,17 +365,16 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'group_name' => $group_name 'group_name' => $group_name,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 退出群组 * 退出群组
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_leave-%E9%80%80%E5%87%BA%E7%BE%A4%E7%BB%84 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_leave-%E9%80%80%E5%87%BA%E7%BE%A4%E7%BB%84
* @param $group_id * @param $group_id
* @param bool $is_dismiss * @return null|array|bool
* @return array|bool|null
*/ */
public function setGroupLeave($group_id, bool $is_dismiss = false) public function setGroupLeave($group_id, bool $is_dismiss = false)
{ {
@@ -385,21 +382,19 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'is_dismiss' => $is_dismiss 'is_dismiss' => $is_dismiss,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 设置群组专属头衔 * 设置群组专属头衔
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_special_title-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E7%BB%84%E4%B8%93%E5%B1%9E%E5%A4%B4%E8%A1%94 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_special_title-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E7%BB%84%E4%B8%93%E5%B1%9E%E5%A4%B4%E8%A1%94
* @param $group_id * @param $group_id
* @param $user_id * @param $user_id
* @param string $special_title * @return null|array|bool
* @param int $duration
* @return array|bool|null
*/ */
public function setGroupSpecialTitle($group_id, $user_id, string $special_title = "", int $duration = -1) public function setGroupSpecialTitle($group_id, $user_id, string $special_title = '', int $duration = -1)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
@@ -407,41 +402,37 @@ class OneBotV11
'group_id' => $group_id, 'group_id' => $group_id,
'user_id' => $user_id, 'user_id' => $user_id,
'special_title' => $special_title, 'special_title' => $special_title,
'duration' => $duration 'duration' => $duration,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 处理加好友请求 * 处理加好友请求
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_friend_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E5%A5%BD%E5%8F%8B%E8%AF%B7%E6%B1%82 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_friend_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E5%A5%BD%E5%8F%8B%E8%AF%B7%E6%B1%82
* @param $flag * @param $flag
* @param bool $approve * @return null|array|bool
* @param string $remark
* @return array|bool|null
*/ */
public function setFriendAddRequest($flag, bool $approve = true, string $remark = "") public function setFriendAddRequest($flag, bool $approve = true, string $remark = '')
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'flag' => $flag, 'flag' => $flag,
'approve' => $approve, 'approve' => $approve,
'remark' => $remark 'remark' => $remark,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 处理加群请求/邀请 * 处理加群请求/邀请
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E7%BE%A4%E8%AF%B7%E6%B1%82%E9%82%80%E8%AF%B7 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_group_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E7%BE%A4%E8%AF%B7%E6%B1%82%E9%82%80%E8%AF%B7
* @param $flag * @param $flag
* @param $sub_type * @param $sub_type
* @param bool $approve * @return null|array|bool
* @param string $reason
* @return array|bool|null
*/ */
public function setGroupAddRequest($flag, $sub_type, bool $approve = true, string $reason = "") public function setGroupAddRequest($flag, $sub_type, bool $approve = true, string $reason = '')
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
@@ -449,15 +440,15 @@ class OneBotV11
'flag' => $flag, 'flag' => $flag,
'sub_type' => $sub_type, 'sub_type' => $sub_type,
'approve' => $approve, 'approve' => $approve,
'reason' => $reason 'reason' => $reason,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取登录号信息 * 获取登录号信息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_login_info-%E8%8E%B7%E5%8F%96%E7%99%BB%E5%BD%95%E5%8F%B7%E4%BF%A1%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_login_info-%E8%8E%B7%E5%8F%96%E7%99%BB%E5%BD%95%E5%8F%B7%E4%BF%A1%E6%81%AF
* @return array|bool|null * @return null|array|bool
*/ */
public function getLoginInfo() public function getLoginInfo()
{ {
@@ -466,10 +457,9 @@ class OneBotV11
/** /**
* 获取陌生人信息 * 获取陌生人信息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_stranger_info-%E8%8E%B7%E5%8F%96%E9%99%8C%E7%94%9F%E4%BA%BA%E4%BF%A1%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_stranger_info-%E8%8E%B7%E5%8F%96%E9%99%8C%E7%94%9F%E4%BA%BA%E4%BF%A1%E6%81%AF
* @param $user_id * @param $user_id
* @param bool $no_cache * @return null|array|bool
* @return array|bool|null
*/ */
public function getStrangerInfo($user_id, bool $no_cache = false) public function getStrangerInfo($user_id, bool $no_cache = false)
{ {
@@ -477,29 +467,28 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'user_id' => $user_id, 'user_id' => $user_id,
'no_cache' => $no_cache 'no_cache' => $no_cache,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取好友列表 * 获取好友列表
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_friend_list-%E8%8E%B7%E5%8F%96%E5%A5%BD%E5%8F%8B%E5%88%97%E8%A1%A8 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_friend_list-%E8%8E%B7%E5%8F%96%E5%A5%BD%E5%8F%8B%E5%88%97%E8%A1%A8
* @return array|bool|null * @return null|array|bool
*/ */
public function getFriendList() public function getFriendList()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取群信息 * 获取群信息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E4%BF%A1%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E4%BF%A1%E6%81%AF
* @param $group_id * @param $group_id
* @param bool $no_cache * @return null|array|bool
* @return array|bool|null
*/ */
public function getGroupInfo($group_id, bool $no_cache = false) public function getGroupInfo($group_id, bool $no_cache = false)
{ {
@@ -507,30 +496,29 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'no_cache' => $no_cache 'no_cache' => $no_cache,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取群列表 * 获取群列表
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_list-%E8%8E%B7%E5%8F%96%E7%BE%A4%E5%88%97%E8%A1%A8 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_list-%E8%8E%B7%E5%8F%96%E7%BE%A4%E5%88%97%E8%A1%A8
* @return array|bool|null * @return null|array|bool
*/ */
public function getGroupList() public function getGroupList()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取群成员信息 * 获取群成员信息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_member_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%88%90%E5%91%98%E4%BF%A1%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_member_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%88%90%E5%91%98%E4%BF%A1%E6%81%AF
* @param $group_id * @param $group_id
* @param $user_id * @param $user_id
* @param bool $no_cache * @return null|array|bool
* @return array|bool|null
*/ */
public function getGroupMemberInfo($group_id, $user_id, bool $no_cache = false) public function getGroupMemberInfo($group_id, $user_id, bool $no_cache = false)
{ {
@@ -539,33 +527,33 @@ class OneBotV11
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'user_id' => $user_id, 'user_id' => $user_id,
'no_cache' => $no_cache 'no_cache' => $no_cache,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取群成员列表 * 获取群成员列表
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_member_list-%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%88%90%E5%91%98%E5%88%97%E8%A1%A8 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_member_list-%E8%8E%B7%E5%8F%96%E7%BE%A4%E6%88%90%E5%91%98%E5%88%97%E8%A1%A8
* @param $group_id * @param $group_id
* @return array|bool|null * @return null|array|bool
*/ */
public function getGroupMemberList($group_id) public function getGroupMemberList($group_id)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id 'group_id' => $group_id,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取群荣誉信息 * 获取群荣誉信息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_honor_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E8%8D%A3%E8%AA%89%E4%BF%A1%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_honor_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E8%8D%A3%E8%AA%89%E4%BF%A1%E6%81%AF
* @param $group_id * @param $group_id
* @param $type * @param $type
* @return array|bool|null * @return null|array|bool
*/ */
public function getGroupHonorInfo($group_id, $type) public function getGroupHonorInfo($group_id, $type)
{ {
@@ -573,45 +561,44 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'group_id' => $group_id, 'group_id' => $group_id,
'type' => $type 'type' => $type,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取 CSRF Token * 获取 CSRF Token
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_csrf_token-%E8%8E%B7%E5%8F%96-csrf-token * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_csrf_token-%E8%8E%B7%E5%8F%96-csrf-token
* @return array|bool|null * @return null|array|bool
*/ */
public function getCsrfToken() public function getCsrfToken()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取 QQ 相关接口凭证 * 获取 QQ 相关接口凭证
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_credentials-%E8%8E%B7%E5%8F%96-qq-%E7%9B%B8%E5%85%B3%E6%8E%A5%E5%8F%A3%E5%87%AD%E8%AF%81 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_credentials-%E8%8E%B7%E5%8F%96-qq-%E7%9B%B8%E5%85%B3%E6%8E%A5%E5%8F%A3%E5%87%AD%E8%AF%81
* @param string $domain * @return null|array|bool
* @return array|bool|null
*/ */
public function getCredentials(string $domain = "") public function getCredentials(string $domain = '')
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'domain' => $domain 'domain' => $domain,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取语音 * 获取语音
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_record-%E8%8E%B7%E5%8F%96%E8%AF%AD%E9%9F%B3 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_record-%E8%8E%B7%E5%8F%96%E8%AF%AD%E9%9F%B3
* @param $file * @param $file
* @param $out_format * @param $out_format
* @return array|bool|null * @return null|array|bool
*/ */
public function getRecord($file, $out_format) public function getRecord($file, $out_format)
{ {
@@ -619,109 +606,107 @@ class OneBotV11
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'file' => $file, 'file' => $file,
'out_format' => $out_format 'out_format' => $out_format,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 获取图片 * 获取图片
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_image-%E8%8E%B7%E5%8F%96%E5%9B%BE%E7%89%87 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_image-%E8%8E%B7%E5%8F%96%E5%9B%BE%E7%89%87
* @param $file * @param $file
* @return array|bool|null * @return null|array|bool
*/ */
public function getImage($file) public function getImage($file)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'file' => $file 'file' => $file,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 检查是否可以发送图片 * 检查是否可以发送图片
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#can_send_image-%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%8F%91%E9%80%81%E5%9B%BE%E7%89%87 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#can_send_image-%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%8F%91%E9%80%81%E5%9B%BE%E7%89%87
* @return array|bool|null * @return null|array|bool
*/ */
public function canSendImage() public function canSendImage()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 检查是否可以发送语音 * 检查是否可以发送语音
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#can_send_record-%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%8F%91%E9%80%81%E8%AF%AD%E9%9F%B3 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#can_send_record-%E6%A3%80%E6%9F%A5%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E5%8F%91%E9%80%81%E8%AF%AD%E9%9F%B3
* @return array|bool|null * @return null|array|bool
*/ */
public function canSendRecord() public function canSendRecord()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取运行状态 * 获取运行状态
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_status-%E8%8E%B7%E5%8F%96%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_status-%E8%8E%B7%E5%8F%96%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81
* @return array|bool|null * @return null|array|bool
*/ */
public function getStatus() public function getStatus()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取版本信息 * 获取版本信息
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_version_info-%E8%8E%B7%E5%8F%96%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_version_info-%E8%8E%B7%E5%8F%96%E7%89%88%E6%9C%AC%E4%BF%A1%E6%81%AF
* @return array|bool|null * @return null|array|bool
*/ */
public function getVersionInfo() public function getVersionInfo()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 重启 OneBot 实现 * 重启 OneBot 实现
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_restart-%E9%87%8D%E5%90%AF-onebot-%E5%AE%9E%E7%8E%B0 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#set_restart-%E9%87%8D%E5%90%AF-onebot-%E5%AE%9E%E7%8E%B0
* @param int $delay * @return null|array|bool
* @return array|bool|null
*/ */
public function setRestart(int $delay = 0) public function setRestart(int $delay = 0)
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__), 'action' => $this->getActionName($this->prefix, __FUNCTION__),
'params' => [ 'params' => [
'delay' => $delay 'delay' => $delay,
] ],
], $this->callback); ], $this->callback);
} }
/** /**
* 清理缓存 * 清理缓存
* @link https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#clean_cache-%E6%B8%85%E7%90%86%E7%BC%93%E5%AD%98 * @see https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#clean_cache-%E6%B8%85%E7%90%86%E7%BC%93%E5%AD%98
* @return array|bool|null * @return null|array|bool
*/ */
public function cleanCache() public function cleanCache()
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $this->getActionName($this->prefix, __FUNCTION__) 'action' => $this->getActionName($this->prefix, __FUNCTION__),
], $this->callback); ], $this->callback);
} }
/** /**
* 获取内置支持的扩展API对象 * 获取内置支持的扩展API对象
* 现支持 go-cqhttp 的扩展API * 现支持 go-cqhttp 的扩展API
* @param string $package_name
* @return mixed
* @throws ZMKnownException * @throws ZMKnownException
* @return mixed
*/ */
public function getExtendedAPI(string $package_name = 'go-cqhttp') public function getExtendedAPI(string $package_name = 'go-cqhttp')
{ {
@@ -730,16 +715,15 @@ class OneBotV11
]; ];
if (isset($table[$package_name])) { if (isset($table[$package_name])) {
return new $table[$package_name]($this->connection, $this->callback, $this->prefix); return new $table[$package_name]($this->connection, $this->callback, $this->prefix);
} else {
throw new ZMKnownException(zm_internal_errcode('E00071'), '无法找到对应的调用扩展类');
} }
throw new ZMKnownException(zm_internal_errcode('E00071'), '无法找到对应的调用扩展类');
} }
public function callExtendedAPI($action, $params = []) public function callExtendedAPI($action, $params = [])
{ {
return $this->processAPI($this->connection, [ return $this->processAPI($this->connection, [
'action' => $action, 'action' => $action,
'params' => $params 'params' => $params,
], $this->callback); ], $this->callback);
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\API; namespace ZM\API;
use Swoole\Coroutine\Http\Client; use Swoole\Coroutine\Http\Client;
use ZM\Console\Console; use ZM\Console\Console;
@@ -16,101 +16,111 @@ class TuringAPI
* @param $api * @param $api
* @return string * @return string
*/ */
public static function getTuringMsg($msg, $user_id, $api) { public static function getTuringMsg($msg, $user_id, $api)
{
$origin = $msg; $origin = $msg;
if (($cq = CQ::getCQ($msg)) !== null) {//如有CQ码则去除 if (($cq = CQ::getCQ($msg)) !== null) {//如有CQ码则去除
if ($cq["type"] == "image") { if ($cq['type'] == 'image') {
$url = $cq["params"]["url"]; $url = $cq['params']['url'];
$msg = str_replace(mb_substr($msg, $cq["start"], $cq["end"] - $cq["start"] + 1), "", $msg); $msg = str_replace(mb_substr($msg, $cq['start'], $cq['end'] - $cq['start'] + 1), '', $msg);
} }
$msg = trim($msg); $msg = trim($msg);
} }
//构建将要发送的json包给图灵 //构建将要发送的json包给图灵
$content = [ $content = [
"reqType" => 0, 'reqType' => 0,
"userInfo" => [ 'userInfo' => [
"apiKey" => $api, 'apiKey' => $api,
"userId" => $user_id 'userId' => $user_id,
] ],
]; ];
if ($msg != "") { if ($msg != '') {
$content["perception"]["inputText"]["text"] = $msg; $content['perception']['inputText']['text'] = $msg;
} }
$msg = trim($msg); $msg = trim($msg);
if (mb_strlen($msg) < 1 && !isset($url)) return "请说出你想说的话"; if (mb_strlen($msg) < 1 && !isset($url)) {
if (isset($url)) { return '请说出你想说的话';
$content["perception"]["inputImage"]["url"] = $url;
$content["reqType"] = 1;
} }
if (!isset($content["perception"])) return "请说出你想说的话"; if (isset($url)) {
$client = new Client("openapi.tuling123.com", 80); $content['perception']['inputImage']['url'] = $url;
$client->setHeaders(["Content-type" => "application/json"]); $content['reqType'] = 1;
$client->post("/openapi/api/v2", json_encode($content, JSON_UNESCAPED_UNICODE)); }
if (!isset($content['perception'])) {
return '请说出你想说的话';
}
$client = new Client('openapi.tuling123.com', 80);
$client->setHeaders(['Content-type' => 'application/json']);
$client->post('/openapi/api/v2', json_encode($content, JSON_UNESCAPED_UNICODE));
$api_return = json_decode($client->body, true); $api_return = json_decode($client->body, true);
if (!isset($api_return["intent"]["code"])) return "XD 哎呀,我脑子突然短路了,请稍后再问我吧!"; if (!isset($api_return['intent']['code'])) {
return 'XD 哎呀,我脑子突然短路了,请稍后再问我吧!';
}
$status = self::getResultStatus($api_return); $status = self::getResultStatus($api_return);
if ($status !== true) { if ($status !== true) {
if ($status == "err:输入文本内容超长(上限150)") return "你的话太多了!!!"; if ($status == 'err:输入文本内容超长(上限150)') {
if ($api_return["intent"]["code"] == 4003) { return '你的话太多了!!!';
return "哎呀,我刚才有点走神了,可能忘记你说什么了,可以重说一遍吗";
} }
Console::error(zm_internal_errcode("E00038") . "图灵机器人发送错误!\n错误原始内容:" . $origin . "\n来自:" . $user_id . "\n错误信息:" . $status); if ($api_return['intent']['code'] == 4003) {
return '哎呀,我刚才有点走神了,可能忘记你说什么了,可以重说一遍吗';
}
Console::error(zm_internal_errcode('E00038') . "图灵机器人发送错误!\n错误原始内容:" . $origin . "\n来自:" . $user_id . "\n错误信息:" . $status);
//echo json_encode($r, 128|256); //echo json_encode($r, 128|256);
return "哎呀,我刚才有点走神了,要不一会儿换一种问题试试?"; return '哎呀,我刚才有点走神了,要不一会儿换一种问题试试?';
} }
$result = $api_return["results"]; $result = $api_return['results'];
//Console::info(Console::setColor(json_encode($result, 128 | 256), "green")); //Console::info(Console::setColor(json_encode($result, 128 | 256), "green"));
$final = ""; $final = '';
foreach ($result as $v) { foreach ($result as $v) {
switch ($v["resultType"]) { switch ($v['resultType']) {
case "url": case 'url':
$final .= "\n" . $v["values"]["url"]; $final .= "\n" . $v['values']['url'];
break; break;
case "text": case 'text':
$final .= "\n" . $v["values"]["text"]; $final .= "\n" . $v['values']['text'];
break; break;
case "image": case 'image':
$final .= "\n" . CQ::image($v["values"]["image"]); $final .= "\n" . CQ::image($v['values']['image']);
break; break;
} }
} }
return trim($final); return trim($final);
} }
public static function getResultStatus($r) { public static function getResultStatus($r)
switch ($r["intent"]["code"]) { {
switch ($r['intent']['code']) {
case 5000: case 5000:
return "err:无解析结果"; return 'err:无解析结果';
case 4000: case 4000:
case 6000: case 6000:
return "err:暂不支持该功能"; return 'err:暂不支持该功能';
case 4001: case 4001:
return "err:加密方式错误"; return 'err:加密方式错误';
case 4005: case 4005:
case 4002: case 4002:
return "err:无功能权限"; return 'err:无功能权限';
case 4003: case 4003:
return "err:该apikey没有可用请求次数"; return 'err:该apikey没有可用请求次数';
case 4007: case 4007:
return "err:apikey不合法"; return 'err:apikey不合法';
case 4100: case 4100:
return "err:userid获取失败"; return 'err:userid获取失败';
case 4200: case 4200:
return "err:上传格式错误"; return 'err:上传格式错误';
case 4300: case 4300:
return "err:批量操作超过限制"; return 'err:批量操作超过限制';
case 4400: case 4400:
return "err:没有上传合法userid"; return 'err:没有上传合法userid';
case 4500: case 4500:
return "err:userid申请个数超过限制"; return 'err:userid申请个数超过限制';
case 4600: case 4600:
return "err:输入内容为空"; return 'err:输入内容为空';
case 4602: case 4602:
return "err:输入文本内容超长(上限150)"; return 'err:输入文本内容超长(上限150)';
case 7002: case 7002:
return "err:上传信息失败"; return 'err:上传信息失败';
case 8008: case 8008:
return "err:服务器错误"; return 'err:服务器错误';
default: default:
return true; return true;
} }

View File

@@ -1,17 +1,14 @@
<?php /** @noinspection PhpMissingReturnTypeInspection */ <?php
/** @noinspection PhpUnused */
declare(strict_types=1);
namespace ZM\API; namespace ZM\API;
/** /**
* Class ZMRobot * Class ZMRobot
* @package ZM\Utils
* @since 1.2 * @since 1.2
* @version V11 * @version V11
*/ */
class ZMRobot extends OneBotV11 class ZMRobot extends OneBotV11
{ {
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation; namespace ZM\Annotation;
use Closure; use Closure;
abstract class AnnotationBase abstract class AnnotationBase
@@ -12,17 +12,26 @@ abstract class AnnotationBase
public $class; public $class;
public function __toString() { public function __toString()
$str = __CLASS__ . ": "; {
$str = __CLASS__ . ': ';
foreach ($this as $k => $v) { foreach ($this as $k => $v) {
$str .= "\n\t" . $k . " => "; $str .= "\n\t" . $k . ' => ';
if (is_string($v)) $str .= "\"$v\""; if (is_string($v)) {
elseif (is_numeric($v)) $str .= $v; $str .= "\"{$v}\"";
elseif (is_bool($v)) $str .= ($v ? "TRUE" : "FALSE"); } elseif (is_numeric($v)) {
elseif (is_array($v)) $str .= json_encode($v, JSON_UNESCAPED_UNICODE); $str .= $v;
elseif ($v instanceof Closure) $str .= "@AnonymousFunction"; } elseif (is_bool($v)) {
elseif (is_null($v)) $str .= "NULL"; $str .= ($v ? 'TRUE' : 'FALSE');
else $str .= "@Unknown"; } elseif (is_array($v)) {
$str .= json_encode($v, JSON_UNESCAPED_UNICODE);
} elseif ($v instanceof Closure) {
$str .= '@AnonymousFunction';
} elseif (is_null($v)) {
$str .= 'NULL';
} else {
$str .= '@Unknown';
}
} }
return $str; return $str;
} }

View File

@@ -1,13 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation; namespace ZM\Annotation;
use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\AnnotationReader;
use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Interfaces\ErgodicAnnotation;
use ZM\Config\ZMConfig;
use ZM\Console\Console;
use ReflectionClass; use ReflectionClass;
use ReflectionException; use ReflectionException;
use ReflectionMethod; use ReflectionMethod;
@@ -17,8 +14,11 @@ use ZM\Annotation\Http\HandleException;
use ZM\Annotation\Http\Middleware; use ZM\Annotation\Http\Middleware;
use ZM\Annotation\Http\MiddlewareClass; use ZM\Annotation\Http\MiddlewareClass;
use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Http\RequestMapping;
use ZM\Annotation\Interfaces\ErgodicAnnotation;
use ZM\Annotation\Interfaces\Level; use ZM\Annotation\Interfaces\Level;
use ZM\Annotation\Module\Closed; use ZM\Annotation\Module\Closed;
use ZM\Config\ZMConfig;
use ZM\Console\Console;
use ZM\Exception\AnnotationException; use ZM\Exception\AnnotationException;
use ZM\Utils\Manager\RouteManager; use ZM\Utils\Manager\RouteManager;
use ZM\Utils\ZMUtil; use ZM\Utils\ZMUtil;
@@ -30,23 +30,27 @@ class AnnotationParser
private $start_time; private $start_time;
private $annotation_map = []; private $annotation_map = [];
private $middleware_map = []; private $middleware_map = [];
private $middlewares = []; private $middlewares = [];
/** @var null|AnnotationReader */ /** @var null|AnnotationReader */
private $reader = null; private $reader;
private $req_mapping = []; private $req_mapping = [];
/** /**
* AnnotationParser constructor. * AnnotationParser constructor.
*/ */
public function __construct() { public function __construct()
{
$this->start_time = microtime(true); $this->start_time = microtime(true);
//$this->loadAnnotationClasses(); //$this->loadAnnotationClasses();
$this->req_mapping[0] = [ $this->req_mapping[0] = [
'id' => 0, 'id' => 0,
'pid' => -1, 'pid' => -1,
'name' => '/' 'name' => '/',
]; ];
} }
@@ -54,13 +58,14 @@ class AnnotationParser
* 注册各个模块类的注解和模块level的排序 * 注册各个模块类的注解和模块level的排序
* @throws ReflectionException * @throws ReflectionException
*/ */
public function registerMods() { public function registerMods()
{
foreach ($this->path_list as $path) { foreach ($this->path_list as $path) {
Console::debug("parsing annotation in " . $path[0].":".$path[1]); Console::debug('parsing annotation in ' . $path[0] . ':' . $path[1]);
$all_class = ZMUtil::getClassesPsr4($path[0], $path[1]); $all_class = ZMUtil::getClassesPsr4($path[0], $path[1]);
$this->reader = new AnnotationReader(); $this->reader = new AnnotationReader();
foreach ($all_class as $v) { foreach ($all_class as $v) {
Console::debug("正在检索 " . $v); Console::debug('正在检索 ' . $v);
$reflection_class = new ReflectionClass($v); $reflection_class = new ReflectionClass($v);
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC); $methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
$class_annotations = $this->reader->getClassAnnotations($reflection_class); $class_annotations = $this->reader->getClassAnnotations($reflection_class);
@@ -85,22 +90,21 @@ class AnnotationParser
*/ */
// 生成主树 // 生成主树
$this->annotation_map[$v]["class_annotations"] = $class_annotations; $this->annotation_map[$v]['class_annotations'] = $class_annotations;
$this->annotation_map[$v]["methods"] = $methods; $this->annotation_map[$v]['methods'] = $methods;
foreach ($methods as $method) { foreach ($methods as $method) {
$this->annotation_map[$v]["methods_annotations"][$method->getName()] = $this->reader->getMethodAnnotations($method); $this->annotation_map[$v]['methods_annotations'][$method->getName()] = $this->reader->getMethodAnnotations($method);
} }
foreach ($this->annotation_map[$v]['class_annotations'] as $vs) {
foreach ($this->annotation_map[$v]["class_annotations"] as $vs) {
$vs->class = $v; $vs->class = $v;
//预处理1将适用于每一个函数的注解到类注解重新注解到每个函数下面 //预处理1将适用于每一个函数的注解到类注解重新注解到每个函数下面
if ($vs instanceof ErgodicAnnotation) { if ($vs instanceof ErgodicAnnotation) {
foreach (($this->annotation_map[$v]["methods"] ?? []) as $method) { foreach (($this->annotation_map[$v]['methods'] ?? []) as $method) {
$copy = clone $vs; $copy = clone $vs;
$copy->method = $method->getName(); $copy->method = $method->getName();
$this->annotation_map[$v]["methods_annotations"][$method->getName()][] = $copy; $this->annotation_map[$v]['methods_annotations'][$method->getName()][] = $copy;
} }
} }
@@ -108,23 +112,24 @@ class AnnotationParser
if ($vs instanceof Closed) { if ($vs instanceof Closed) {
unset($this->annotation_map[$v]); unset($this->annotation_map[$v]);
continue 2; continue 2;
} elseif ($vs instanceof MiddlewareClass) { }
if ($vs instanceof MiddlewareClass) {
//注册中间件本身的类,标记到 middlewares 属性中 //注册中间件本身的类,标记到 middlewares 属性中
Console::debug("正在注册中间件 " . $reflection_class->getName()); Console::debug('正在注册中间件 ' . $reflection_class->getName());
$rs = $this->registerMiddleware($vs, $reflection_class); $rs = $this->registerMiddleware($vs, $reflection_class);
$this->middlewares[$rs["name"]] = $rs; $this->middlewares[$rs['name']] = $rs;
} }
} }
$inserted = []; $inserted = [];
//预处理3处理每个函数上面的特殊注解就是需要操作一些东西的 //预处理3处理每个函数上面的特殊注解就是需要操作一些东西的
foreach (($this->annotation_map[$v]["methods_annotations"] ?? []) as $method_name => $methods_annotations) { foreach (($this->annotation_map[$v]['methods_annotations'] ?? []) as $method_name => $methods_annotations) {
foreach ($methods_annotations as $method_anno) { foreach ($methods_annotations as $method_anno) {
/** @var AnnotationBase $method_anno */ /* @var AnnotationBase $method_anno */
$method_anno->class = $v; $method_anno->class = $v;
$method_anno->method = $method_name; $method_anno->method = $method_name;
if (!($method_anno instanceof Middleware) && ($middlewares = ZMConfig::get("global", "runtime")["global_middleware_binding"][get_class($method_anno)] ?? []) !== []) { if (!($method_anno instanceof Middleware) && ($middlewares = ZMConfig::get('global', 'runtime')['global_middleware_binding'][get_class($method_anno)] ?? []) !== []) {
if (!isset($inserted[$v][$method_name])) { if (!isset($inserted[$v][$method_name])) {
// 在这里在其他中间件前插入插入全局的中间件 // 在这里在其他中间件前插入插入全局的中间件
foreach ($middlewares as $middleware) { foreach ($middlewares as $middleware) {
@@ -146,23 +151,25 @@ class AnnotationParser
} }
} }
} }
Console::debug("解析注解完毕!"); Console::debug('解析注解完毕!');
} }
public function generateAnnotationEvents(): array { public function generateAnnotationEvents(): array
{
$o = []; $o = [];
foreach ($this->annotation_map as $obj) { foreach ($this->annotation_map as $obj) {
// 这里的ErgodicAnnotation是为了解决类上的注解可穿透到方法上的问题 // 这里的ErgodicAnnotation是为了解决类上的注解可穿透到方法上的问题
foreach (($obj["class_annotations"] ?? []) as $class_annotation) { foreach (($obj['class_annotations'] ?? []) as $class_annotation) {
if ($class_annotation instanceof ErgodicAnnotation) continue; if ($class_annotation instanceof ErgodicAnnotation) {
else $o[get_class($class_annotation)][] = $class_annotation; continue;
}
$o[get_class($class_annotation)][] = $class_annotation;
} }
foreach (($obj["methods_annotations"] ?? []) as $methods_annotations) { foreach (($obj['methods_annotations'] ?? []) as $methods_annotations) {
foreach ($methods_annotations as $annotation) { foreach ($methods_annotations as $annotation) {
$o[get_class($annotation)][] = $annotation; $o[get_class($annotation)][] = $annotation;
} }
} }
} }
foreach ($o as $k => $v) { foreach ($o as $k => $v) {
$this->sortByLevel($o, $k); $this->sortByLevel($o, $k);
@@ -170,55 +177,36 @@ class AnnotationParser
return $o; return $o;
} }
/** public function getMiddlewares(): array
* @return array {
*/ return $this->middlewares;
public function getMiddlewares(): array { return $this->middlewares; } }
/** public function getMiddlewareMap(): array
* @return array {
*/ return $this->middleware_map;
public function getMiddlewareMap(): array { return $this->middleware_map; } }
/** public function getReqMapping(): array
* @return array {
*/ return $this->req_mapping;
public function getReqMapping(): array { return $this->req_mapping; } }
/** /**
* @param $path * @param $path
* @param $indoor_name * @param $indoor_name
*/ */
public function addRegisterPath($path, $indoor_name) { $this->path_list[] = [$path, $indoor_name]; } public function addRegisterPath($path, $indoor_name)
{
//private function below $this->path_list[] = [$path, $indoor_name];
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class): array {
$result = [
"class" => "\\" . $reflection_class->getName(),
"name" => $vs->name
];
foreach ($reflection_class->getMethods() as $vss) {
$method_annotations = $this->reader->getMethodAnnotations($vss);
foreach ($method_annotations as $vsss) {
if ($vsss instanceof HandleBefore) $result["before"] = $vss->getName();
if ($vsss instanceof HandleAfter) $result["after"] = $vss->getName();
if ($vsss instanceof HandleException) {
$result["exceptions"][$vsss->class_name] = $vss->getName();
}
}
}
return $result;
} }
/** /**
* @internal 用于 level 排序
* @param $events * @param $events
* @param string $class_name * @internal 用于 level 排序
* @param string $prefix
*/ */
public function sortByLevel(&$events, string $class_name, $prefix = "") { public function sortByLevel(&$events, string $class_name, string $prefix = '')
{
if (is_a($class_name, Level::class, true)) { if (is_a($class_name, Level::class, true)) {
$class_name .= $prefix; $class_name .= $prefix;
usort($events[$class_name], function ($a, $b) { usort($events[$class_name], function ($a, $b) {
@@ -232,12 +220,13 @@ class AnnotationParser
/** /**
* @throws AnnotationException * @throws AnnotationException
*/ */
public function verifyMiddlewares() { public function verifyMiddlewares()
if ((ZMConfig::get("global", "runtime")["middleware_error_policy"] ?? 1) === 2) { {
if ((ZMConfig::get('global', 'runtime')['middleware_error_policy'] ?? 1) === 2) {
//我承认套三层foreach很不优雅但是这个会很快的。 //我承认套三层foreach很不优雅但是这个会很快的。
foreach($this->middleware_map as $class => $v) { foreach ($this->middleware_map as $v) {
foreach ($v as $method => $vs) { foreach ($v as $vs) {
foreach($vs as $mid) { foreach ($vs as $mid) {
if (!isset($this->middlewares[$mid->middleware])) { if (!isset($this->middlewares[$mid->middleware])) {
throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$mid->middleware}\"!"); throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$mid->middleware}\"!");
} }
@@ -246,4 +235,35 @@ class AnnotationParser
} }
} }
} }
public function getRunTime()
{
return microtime(true) - $this->start_time;
}
//private function below
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class): array
{
$result = [
'class' => '\\' . $reflection_class->getName(),
'name' => $vs->name,
];
foreach ($reflection_class->getMethods() as $vss) {
$method_annotations = $this->reader->getMethodAnnotations($vss);
foreach ($method_annotations as $vsss) {
if ($vsss instanceof HandleBefore) {
$result['before'] = $vss->getName();
}
if ($vsss instanceof HandleAfter) {
$result['after'] = $vss->getName();
}
if ($vsss instanceof HandleException) {
$result['exceptions'][$vsss->class_name] = $vss->getName();
}
}
}
return $result;
}
} }

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class CQAPIResponse * Class CQAPIResponse
* @package ZM\Annotation\CQ
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
@@ -11,7 +12,6 @@ use ZM\Annotation\Interfaces\Level;
* Class CQAfter * Class CQAfter
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* @package ZM\Annotation\CQ
*/ */
class CQAfter extends AnnotationBase implements Level class CQAfter extends AnnotationBase implements Level
{ {
@@ -26,14 +26,16 @@ class CQAfter extends AnnotationBase implements Level
/** /**
* @return mixed * @return mixed
*/ */
public function getLevel() { public function getLevel()
{
return $this->level; return $this->level;
} }
/** /**
* @param mixed $level * @param mixed $level
*/ */
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
@@ -13,7 +13,6 @@ use ZM\Annotation\Interfaces\Level;
* Class CQBefore * Class CQBefore
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* @package ZM\Annotation\CQ
*/ */
class CQBefore extends AnnotationBase implements Level class CQBefore extends AnnotationBase implements Level
{ {
@@ -28,15 +27,16 @@ class CQBefore extends AnnotationBase implements Level
/** /**
* @return mixed * @return mixed
*/ */
public function getLevel(): int { public function getLevel(): int
{
return $this->level; return $this->level;
} }
/** /**
* @param mixed $level * @param mixed $level
*/ */
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
@@ -11,43 +12,55 @@ use ZM\Annotation\Interfaces\Level;
* Class CQCommand * Class CQCommand
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
* @package ZM\Annotation\CQ
*/ */
class CQCommand extends AnnotationBase implements Level class CQCommand extends AnnotationBase implements Level
{ {
/** @var string */ /** @var string */
public $match = ""; public $match = '';
/** @var string */ /** @var string */
public $pattern = ""; public $pattern = '';
/** @var string */ /** @var string */
public $regex = ""; public $regex = '';
/** @var string */ /** @var string */
public $start_with = ""; public $start_with = '';
/** @var string */ /** @var string */
public $end_with = ""; public $end_with = '';
/** @var string */ /** @var string */
public $keyword = ""; public $keyword = '';
/** @var string[] */ /** @var string[] */
public $alias = []; public $alias = [];
/** @var string */ /** @var string */
public $message_type = ""; public $message_type = '';
/** @var int */ /** @var int */
public $user_id = 0; public $user_id = 0;
/** @var int */ /** @var int */
public $group_id = 0; public $group_id = 0;
/** @var int */ /** @var int */
public $discuss_id = 0; public $discuss_id = 0;
/** @var int */ /** @var int */
public $level = 20; public $level = 20;
/** public function getLevel(): int
* @return int {
*/ return $this->level;
public function getLevel(): int { return $this->level; } }
/** /**
* @param int $level * @param int $level
*/ */
public function setLevel($level) { $this->level = $level; } public function setLevel($level)
{
$this->level = $level;
}
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
@@ -11,30 +12,39 @@ use ZM\Annotation\Interfaces\Level;
* Class CQMessage * Class CQMessage
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
* @package ZM\Annotation\CQ
*/ */
class CQMessage extends AnnotationBase implements Level class CQMessage extends AnnotationBase implements Level
{ {
/** /**
* @var string * @var string
*/ */
public $message_type = ""; public $message_type = '';
/** @var int */ /** @var int */
public $user_id = 0; public $user_id = 0;
/** @var int */ /** @var int */
public $group_id = 0; public $group_id = 0;
/** @var int */ /** @var int */
public $discuss_id = 0; public $discuss_id = 0;
/** @var string */ /** @var string */
public $message = ""; public $message = '';
/** @var string */ /** @var string */
public $raw_message = ""; public $raw_message = '';
/** @var int */ /** @var int */
public $level = 20; public $level = 20;
public function getLevel(): int { return $this->level; } public function getLevel(): int
{
return $this->level;
}
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
@@ -12,7 +13,6 @@ use ZM\Annotation\Interfaces\Level;
* Class CQMetaEvent * Class CQMetaEvent
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
* @package ZM\Annotation\CQ
*/ */
class CQMetaEvent extends AnnotationBase implements Level class CQMetaEvent extends AnnotationBase implements Level
{ {
@@ -21,18 +21,23 @@ class CQMetaEvent extends AnnotationBase implements Level
* @Required() * @Required()
*/ */
public $meta_event_type = ''; public $meta_event_type = '';
/** @var int */ /** @var int */
public $level; public $level;
/** /**
* @return mixed * @return mixed
*/ */
public function getLevel(): int { return $this->level; } public function getLevel(): int
{
return $this->level;
}
/** /**
* @param int $level * @param int $level
*/ */
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
@@ -11,32 +12,34 @@ use ZM\Annotation\Interfaces\Level;
* Class CQNotice * Class CQNotice
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
* @package ZM\Annotation\CQ
*/ */
class CQNotice extends AnnotationBase implements Level class CQNotice extends AnnotationBase implements Level
{ {
/** @var string */ /** @var string */
public $notice_type = ""; public $notice_type = '';
/** @var string */ /** @var string */
public $sub_type = ""; public $sub_type = '';
/** @var int */ /** @var int */
public $group_id = 0; public $group_id = 0;
/** @var int */ /** @var int */
public $operator_id = 0; public $operator_id = 0;
/** @var int */ /** @var int */
public $level = 20; public $level = 20;
/** public function getLevel(): int
* @return int {
*/
public function getLevel(): int {
return $this->level; return $this->level;
} }
/** /**
* @param int $level * @param int $level
*/ */
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\CQ; namespace ZM\Annotation\CQ;
@@ -11,32 +12,34 @@ use ZM\Annotation\Interfaces\Level;
* Class CQRequest * Class CQRequest
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
* @package ZM\Annotation\CQ
*/ */
class CQRequest extends AnnotationBase implements Level class CQRequest extends AnnotationBase implements Level
{ {
/** @var string */ /** @var string */
public $request_type = ""; public $request_type = '';
/** @var string */ /** @var string */
public $sub_type = ""; public $sub_type = '';
/** @var int */ /** @var int */
public $user_id = 0; public $user_id = 0;
/** @var string */ /** @var string */
public $comment = ""; public $comment = '';
/** @var int */ /** @var int */
public $level = 20; public $level = 20;
/** public function getLevel(): int
* @return int {
*/
public function getLevel(): int {
return $this->level; return $this->level;
} }
/** /**
* @param int $level * @param int $level
*/ */
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Command; namespace ZM\Annotation\Command;
@@ -9,7 +10,6 @@ use ZM\Annotation\AnnotationBase;
/** /**
* Class TerminalCommand * Class TerminalCommand
* @package ZM\Annotation\Command
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
@@ -26,5 +26,5 @@ class TerminalCommand extends AnnotationBase
/** /**
* @var string * @var string
*/ */
public $description = ""; public $description = '';
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
@@ -12,7 +13,6 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
* Class Controller * Class Controller
* @Annotation * @Annotation
* @Target("CLASS") * @Target("CLASS")
* @package ZM\Annotation\Http
*/ */
class Controller extends AnnotationBase implements ErgodicAnnotation class Controller extends AnnotationBase implements ErgodicAnnotation
{ {

View File

@@ -1,15 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class HandleAfter * Class HandleAfter
* @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,15 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class HandleBefore * Class HandleBefore
* @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use Exception; use Exception;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class HandleException * Class HandleException
* @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
@@ -11,7 +11,6 @@ use ZM\Annotation\Interfaces\ErgodicAnnotation;
/** /**
* Class Middleware * Class Middleware
* @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
*/ */

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class MiddlewareClass * Class MiddlewareClass
* @package ZM\Annotation\Http
* @Annotation * @Annotation
* @Target("CLASS") * @Target("CLASS")
*/ */

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
@@ -11,7 +12,6 @@ use ZM\Annotation\AnnotationBase;
* Class RequestMapping * Class RequestMapping
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* @package ZM\Annotation\Http
*/ */
class RequestMapping extends AnnotationBase class RequestMapping extends AnnotationBase
{ {

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Http; namespace ZM\Annotation\Http;
@@ -9,21 +10,26 @@ use ZM\Annotation\AnnotationBase;
/** /**
* Class RequestMethod * Class RequestMethod
* @Annotation * @Annotation
* @package ZM\Annotation\Http
*/ */
class RequestMethod extends AnnotationBase class RequestMethod extends AnnotationBase
{ {
public const GET = 'GET';
public const POST = 'POST';
public const PUT = 'PUT';
public const PATCH = 'PATCH';
public const DELETE = 'DELETE';
public const OPTIONS = 'OPTIONS';
public const HEAD = 'HEAD';
/** /**
* @var string * @var string
* @Required() * @Required()
*/ */
public $method = self::GET; public $method = self::GET;
public const GET = 'GET';
public const POST = 'POST';
public const PUT = 'PUT';
public const PATCH = 'PATCH';
public const DELETE = 'DELETE';
public const OPTIONS = 'OPTIONS';
public const HEAD = 'HEAD';
} }

View File

@@ -1,10 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Interfaces; namespace ZM\Annotation\Interfaces;
interface CustomAnnotation interface CustomAnnotation
{ {
} }

View File

@@ -1,10 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Interfaces; namespace ZM\Annotation\Interfaces;
interface ErgodicAnnotation interface ErgodicAnnotation
{ {
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Interfaces; namespace ZM\Annotation\Interfaces;
interface Level interface Level
{ {
public function getLevel(); public function getLevel();

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Interfaces; namespace ZM\Annotation\Interfaces;
interface Rule interface Rule
{ {
public function getRule(); public function getRule();

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Module; namespace ZM\Annotation\Module;
@@ -10,9 +11,7 @@ use ZM\Annotation\AnnotationBase;
* Class Closed * Class Closed
* @Annotation * @Annotation
* @Target("CLASS") * @Target("CLASS")
* @package ZM\Annotation\Module
*/ */
class Closed extends AnnotationBase class Closed extends AnnotationBase
{ {
} }

View File

@@ -1,21 +1,20 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
/** /**
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* Class OnCloseEvent * Class OnCloseEvent
* @package ZM\Annotation\Swoole
*/ */
class OnCloseEvent extends OnSwooleEventBase class OnCloseEvent extends OnSwooleEventBase
{ {
/** /**
* @var string * @var string
*/ */
public $connect_type = "default"; public $connect_type = 'default';
} }

View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Target;
/**
* @Annotation
* @Target("METHOD")
* @since 2.7.0
*/
class OnManagerStartEvent extends OnSwooleEventBase
{
}

View File

@@ -1,21 +1,20 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
/** /**
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* Class OnMessageEvent * Class OnMessageEvent
* @package ZM\Annotation\Swoole
*/ */
class OnMessageEvent extends OnSwooleEventBase class OnMessageEvent extends OnSwooleEventBase
{ {
/** /**
* @var string * @var string
*/ */
public $connect_type = "default"; public $connect_type = 'default';
} }

View File

@@ -1,21 +1,20 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
/** /**
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* Class OnOpenEvent * Class OnOpenEvent
* @package ZM\Annotation\Swoole
*/ */
class OnOpenEvent extends OnSwooleEventBase class OnOpenEvent extends OnSwooleEventBase
{ {
/** /**
* @var string * @var string
*/ */
public $connect_type = "default"; public $connect_type = 'default';
} }

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class OnPipeMessageEvent * Class OnPipeMessageEvent
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
/** /**
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* Class OnRequestEvent * Class OnRequestEvent
* @package ZM\Annotation\Swoole
*/ */
class OnRequestEvent extends OnSwooleEventBase class OnRequestEvent extends OnSwooleEventBase
{ {

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
@@ -8,11 +9,9 @@ use ZM\Annotation\AnnotationBase;
/** /**
* Class OnSave * Class OnSave
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
class OnSave extends AnnotationBase class OnSave extends AnnotationBase
{ {
} }

View File

@@ -1,15 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class ZMSetup * Class ZMSetup
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
@@ -8,7 +9,6 @@ use ZM\Annotation\AnnotationBase;
/** /**
* Class OnWorkerStart * Class OnWorkerStart
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
@@ -10,7 +11,6 @@ use Doctrine\Common\Annotations\Annotation\Target;
* Class OnSwooleEvent * Class OnSwooleEvent
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* @package ZM\Annotation\Swoole
*/ */
class OnSwooleEvent extends OnSwooleEventBase class OnSwooleEvent extends OnSwooleEventBase
{ {
@@ -20,17 +20,13 @@ class OnSwooleEvent extends OnSwooleEventBase
*/ */
public $type; public $type;
/** public function getType(): string
* @return string {
*/
public function getType(): string {
return $this->type; return $this->type;
} }
/** public function setType(string $type)
* @param string $type {
*/
public function setType(string $type) {
$this->type = $type; $this->type = $type;
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
use ZM\Annotation\Interfaces\Level; use ZM\Annotation\Interfaces\Level;
use ZM\Annotation\Interfaces\Rule; use ZM\Annotation\Interfaces\Rule;
@@ -13,37 +13,33 @@ abstract class OnSwooleEventBase extends AnnotationBase implements Level, Rule
/** /**
* @var string * @var string
*/ */
public $rule = ""; public $rule = '';
/** /**
* @var int * @var int
*/ */
public $level = 20; public $level = 20;
/** public function getRule()
* @return string {
*/ return $this->rule !== '' ? $this->rule : true;
public function getRule(): string {
return $this->rule !== "" ? $this->rule : true;
} }
/** public function setRule(string $rule)
* @param string $rule {
*/
public function setRule(string $rule) {
$this->rule = $rule; $this->rule = $rule;
} }
/** public function getLevel(): int
* @return int {
*/
public function getLevel(): int {
return $this->level; return $this->level;
} }
/** /**
* @param int $level * @param int $level
*/ */
public function setLevel($level) { public function setLevel($level)
{
$this->level = $level; $this->level = $level;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
@@ -10,7 +11,6 @@ use ZM\Annotation\Interfaces\Rule;
/** /**
* Class OnTask * Class OnTask
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */
@@ -25,12 +25,13 @@ class OnTask extends AnnotationBase implements Rule
/** /**
* @var string * @var string
*/ */
public $rule = ""; public $rule = '';
/** /**
* @return mixed * @return mixed
*/ */
public function getRule(): string { public function getRule(): string
{
return $this->rule; return $this->rule;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
@@ -7,7 +8,6 @@ use Doctrine\Common\Annotations\Annotation\Target;
/** /**
* Class OnTaskEvent * Class OnTaskEvent
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
*/ */

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class OnTick * Class OnTick
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("METHOD") * @Target("METHOD")
* @since 1.2 * @since 1.2

View File

@@ -1,16 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Annotation\Swoole; namespace ZM\Annotation\Swoole;
use Doctrine\Common\Annotations\Annotation\Required; use Doctrine\Common\Annotations\Annotation\Required;
use Doctrine\Common\Annotations\Annotation\Target; use Doctrine\Common\Annotations\Annotation\Target;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
/** /**
* Class SwooleHandler * Class SwooleHandler
* @package ZM\Annotation\Swoole
* @Annotation * @Annotation
* @Target("ALL") * @Target("ALL")
*/ */

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command; namespace ZM\Command;
@@ -16,44 +17,52 @@ class BuildCommand extends Command
{ {
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'build'; protected static $defaultName = 'build';
/** /**
* @var OutputInterface * @var OutputInterface
*/ */
private $output = null; private $output;
protected function configure() { protected function configure()
$this->setDescription("Build an \".phar\" file | 将项目构建一个phar包"); {
$this->setHelp("此功能将会把整个项目打包为phar"); $this->setDescription('Build an ".phar" file | 将项目构建一个phar包');
$this->addOption("target", "D", InputOption::VALUE_REQUIRED, "Output Directory | 指定输出目录"); $this->setHelp('此功能将会把整个项目打包为phar');
$this->addOption('target', 'D', InputOption::VALUE_REQUIRED, 'Output Directory | 指定输出目录');
// ... // ...
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->output = $output; $this->output = $output;
$target_dir = $input->getOption("target") ?? (WORKING_DIR); $target_dir = $input->getOption('target') ?? (WORKING_DIR);
if (mb_strpos($target_dir, "../")) $target_dir = realpath($target_dir); if (mb_strpos($target_dir, '../')) {
$target_dir = realpath($target_dir);
}
if ($target_dir === false) { if ($target_dir === false) {
$output->writeln(TermColor::color8(31) . zm_internal_errcode("E00039") . "Error: No such file or directory (" . $target_dir . ")" . TermColor::RESET); $output->writeln(TermColor::color8(31) . zm_internal_errcode('E00039') . 'Error: No such file or directory (' . $target_dir . ')' . TermColor::RESET);
return 1; return 1;
} }
$output->writeln("Target: " . $target_dir); $output->writeln('Target: ' . $target_dir);
if (mb_substr($target_dir, -1, 1) !== '/') $target_dir .= "/"; if (mb_substr($target_dir, -1, 1) !== '/') {
$target_dir .= '/';
}
if (ini_get('phar.readonly') == 1) { if (ini_get('phar.readonly') == 1) {
$output->writeln(TermColor::color8(31) . zm_internal_errcode("E00040") . "You need to set \"phar.readonly\" to \"Off\"!"); $output->writeln(TermColor::color8(31) . zm_internal_errcode('E00040') . 'You need to set "phar.readonly" to "Off"!');
$output->writeln(TermColor::color8(31) . "See: https://stackoverflow.com/questions/34667606/cant-enable-phar-writing"); $output->writeln(TermColor::color8(31) . 'See: https://stackoverflow.com/questions/34667606/cant-enable-phar-writing');
return 1; return 1;
} }
if (!is_dir($target_dir)) { if (!is_dir($target_dir)) {
$output->writeln(TermColor::color8(31) . zm_internal_errcode("E00039") . "Error: No such file or directory ($target_dir)" . TermColor::RESET); $output->writeln(TermColor::color8(31) . zm_internal_errcode('E00039') . "Error: No such file or directory ({$target_dir})" . TermColor::RESET);
return 1; return 1;
} }
$filename = "server.phar"; $filename = 'server.phar';
$this->build($target_dir, $filename); $this->build($target_dir, $filename);
return 0; return 0;
} }
private function build($target_dir, $filename) { private function build($target_dir, $filename)
{
@unlink($target_dir . $filename); @unlink($target_dir . $filename);
$phar = new Phar($target_dir . $filename); $phar = new Phar($target_dir . $filename);
$phar->startBuffering(); $phar->startBuffering();
@@ -62,7 +71,7 @@ class BuildCommand extends Command
$all = DataProvider::scanDirFiles(DataProvider::getSourceRootDir(), true, true); $all = DataProvider::scanDirFiles(DataProvider::getSourceRootDir(), true, true);
$all = array_filter($all, function ($x) { $all = array_filter($all, function ($x) {
$dirs = preg_match("/(^(bin|config|resources|src|vendor)\/|^(composer\.json|README\.md)$)/", $x); $dirs = preg_match('/(^(bin|config|resources|src|vendor)\\/|^(composer\\.json|README\\.md)$)/', $x);
return !($dirs !== 1); return !($dirs !== 1);
}); });
@@ -71,15 +80,15 @@ class BuildCommand extends Command
$archive_dir = DataProvider::getSourceRootDir(); $archive_dir = DataProvider::getSourceRootDir();
foreach ($all as $k => $v) { foreach ($all as $k => $v) {
$phar->addFile($archive_dir . "/" . $v, $v); $phar->addFile($archive_dir . '/' . $v, $v);
$progress->current($k + 1, "Adding " . $v); $progress->current($k + 1, 'Adding ' . $v);
} }
$phar->setStub( $phar->setStub(
"#!/usr/bin/env php\n" . "#!/usr/bin/env php\n" .
$phar->createDefaultStub(LOAD_MODE == 0 ? "src/entry.php" : "vendor/zhamao/framework/src/entry.php") $phar->createDefaultStub(LOAD_MODE == 0 ? 'src/entry.php' : 'vendor/zhamao/framework/src/entry.php')
); );
$phar->stopBuffering(); $phar->stopBuffering();
$this->output->writeln("Successfully built. Location: " . $target_dir . "$filename"); $this->output->writeln('Successfully built. Location: ' . $target_dir . "{$filename}");
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command; namespace ZM\Command;
@@ -14,49 +15,53 @@ class CheckConfigCommand extends Command
private $need_update = false; private $need_update = false;
protected function configure() { protected function configure()
$this->setDescription("检查配置文件是否和框架当前版本有更新"); {
$this->setDescription('检查配置文件是否和框架当前版本有更新');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
if (LOAD_MODE !== 1) { if (LOAD_MODE !== 1) {
$output->writeln("<error>仅限在Composer依赖模式中使用此命令</error>"); $output->writeln('<error>仅限在Composer依赖模式中使用此命令</error>');
return 1; return 1;
} }
$current_cfg = getcwd() . "/config/"; $current_cfg = getcwd() . '/config/';
$remote_cfg = include_once FRAMEWORK_ROOT_DIR . "/config/global.php"; $remote_cfg = include_once FRAMEWORK_ROOT_DIR . '/config/global.php';
if (file_exists($current_cfg . "global.php")) { if (file_exists($current_cfg . 'global.php')) {
$this->check($remote_cfg, "global.php", $output); $this->check($remote_cfg, 'global.php', $output);
} }
if (file_exists($current_cfg . "global.development.php")) { if (file_exists($current_cfg . 'global.development.php')) {
$this->check($remote_cfg, "global.development.php", $output); $this->check($remote_cfg, 'global.development.php', $output);
} }
if (file_exists($current_cfg . "global.staging.php")) { if (file_exists($current_cfg . 'global.staging.php')) {
$this->check($remote_cfg, "global.staging.php", $output); $this->check($remote_cfg, 'global.staging.php', $output);
} }
if (file_exists($current_cfg . "global.production.php")) { if (file_exists($current_cfg . 'global.production.php')) {
$this->check($remote_cfg, "global.production.php", $output); $this->check($remote_cfg, 'global.production.php', $output);
} }
if ($this->need_update === true) { if ($this->need_update === true) {
$output->writeln("<comment>有配置文件需要更新,详情见文档 `https://framework.zhamao.xin/update/config`</comment>"); $output->writeln('<comment>有配置文件需要更新,详情见文档 `https://framework.zhamao.xin/update/config`</comment>');
} else { } else {
$output->writeln("<info>配置文件暂无更新!</info>"); $output->writeln('<info>配置文件暂无更新!</info>');
} }
return 0; return 0;
} }
/** /**
* @noinspection PhpIncludeInspection * @param mixed $remote
* @param mixed $local
*/ */
private function check($remote, $local, OutputInterface $out) { private function check($remote, $local, OutputInterface $out)
$local_file = include_once WORKING_DIR . "/config/".$local; {
$local_file = include_once WORKING_DIR . '/config/' . $local;
if ($local_file === true) { if ($local_file === true) {
$local_file = ZMConfig::get("global"); $local_file = ZMConfig::get('global');
} }
foreach($remote as $k => $v) { foreach ($remote as $k => $v) {
if (!isset($local_file[$k])) { if (!isset($local_file[$k])) {
$out->writeln("<comment>配置文件 ".$local . " 需要更新!(当前配置文件缺少 `$k` 字段配置)</comment>"); $out->writeln('<comment>配置文件 ' . $local . " 需要更新!(当前配置文件缺少 `{$k}` 字段配置)</comment>");
$this->need_update = true; $this->need_update = true;
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Daemon; namespace ZM\Command\Daemon;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -11,14 +11,15 @@ use ZM\Framework;
abstract class DaemonCommand extends Command abstract class DaemonCommand extends Command
{ {
protected $daemon_file = null; protected $daemon_file;
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
$file = Framework::getProcessState(ZM_PROCESS_MASTER); $file = Framework::getProcessState(ZM_PROCESS_MASTER);
if ($file === false || posix_getsid(intval($file["pid"])) === false) { if ($file === false || posix_getsid(intval($file['pid'])) === false) {
$output->writeln("<comment>未检测到正在运行的守护进程或框架进程!</comment>"); $output->writeln('<comment>未检测到正在运行的守护进程或框架进程!</comment>');
Framework::removeProcessState(ZM_PROCESS_MASTER); Framework::removeProcessState(ZM_PROCESS_MASTER);
die(); exit(1);
} }
$this->daemon_file = $file; $this->daemon_file = $file;
return 0; return 0;

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Daemon; namespace ZM\Command\Daemon;
@@ -11,14 +12,16 @@ class DaemonReloadCommand extends DaemonCommand
{ {
protected static $defaultName = 'daemon:reload'; protected static $defaultName = 'daemon:reload';
protected function configure() { protected function configure()
$this->setDescription("重载框架"); {
$this->setDescription('重载框架');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output); parent::execute($input, $output);
Process::kill(intval($this->daemon_file["pid"]), SIGUSR1); Process::kill(intval($this->daemon_file['pid']), SIGUSR1);
$output->writeln("<info>成功重载!</info>"); $output->writeln('<info>成功重载!</info>');
return 0; return 0;
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Daemon; namespace ZM\Command\Daemon;
@@ -10,20 +11,23 @@ class DaemonStatusCommand extends DaemonCommand
{ {
protected static $defaultName = 'daemon:status'; protected static $defaultName = 'daemon:status';
protected function configure() { protected function configure()
$this->setDescription("查看框架的运行状态"); {
$this->setDescription('查看框架的运行状态');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output); parent::execute($input, $output);
$output->writeln("<info>框架" . ($this->daemon_file["daemon"] ? "以守护进程模式" : "") . "运行中pid" . $this->daemon_file["pid"] . "</info>"); $output->writeln('<info>框架' . ($this->daemon_file['daemon'] ? '以守护进程模式' : '') . '运行中pid' . $this->daemon_file['pid'] . '</info>');
if ($this->daemon_file["daemon"]) { if ($this->daemon_file['daemon']) {
$output->writeln("<comment>----- 以下是stdout内容 -----</comment>"); $output->writeln('<comment>----- 以下是stdout内容 -----</comment>');
$stdout = file_get_contents($this->daemon_file["stdout"]); $stdout = file_get_contents($this->daemon_file['stdout']);
$stdout = explode("\n", $stdout); $stdout = explode("\n", $stdout);
for ($i = 15; $i > 0; --$i) { for ($i = 15; $i > 0; --$i) {
if (isset($stdout[count($stdout) - $i])) if (isset($stdout[count($stdout) - $i])) {
echo $stdout[count($stdout) - $i] . PHP_EOL; echo $stdout[count($stdout) - $i] . PHP_EOL;
}
} }
} }
return 0; return 0;

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Daemon; namespace ZM\Command\Daemon;
@@ -12,22 +13,24 @@ class DaemonStopCommand extends DaemonCommand
{ {
protected static $defaultName = 'daemon:stop'; protected static $defaultName = 'daemon:stop';
protected function configure() { protected function configure()
$this->setDescription("停止运行的框架"); {
$this->setDescription('停止运行的框架');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output); parent::execute($input, $output);
Process::kill(intval($this->daemon_file["pid"]), SIGTERM); Process::kill(intval($this->daemon_file['pid']), SIGTERM);
$i = 10; $i = 10;
while (Framework::getProcessState(ZM_PROCESS_MASTER) !== false && $i > 0) { while (Framework::getProcessState(ZM_PROCESS_MASTER) !== false && $i > 0) {
sleep(1); sleep(1);
--$i; --$i;
} }
if ($i === 0) { if ($i === 0) {
$output->writeln("<error>停止失败请检查进程pid #" . $this->daemon_file["pid"] . " 是否响应!</error>"); $output->writeln('<error>停止失败请检查进程pid #' . $this->daemon_file['pid'] . ' 是否响应!</error>');
} else { } else {
$output->writeln("<info>成功停止!</info>"); $output->writeln('<info>成功停止!</info>');
} }
return 0; return 0;
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Generate; namespace ZM\Command\Generate;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -15,28 +15,31 @@ class SystemdGenerateCommand extends Command
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'generate:systemd'; protected static $defaultName = 'generate:systemd';
protected function configure() { protected function configure()
$this->setDescription("生成框架的 systemd 配置文件"); {
$this->setDescription('生成框架的 systemd 配置文件');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config'); ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
$path = $this->generate(); $path = $this->generate();
$output->writeln("<info>成功生成 systemd 文件,位置:" . $path . "</info>"); $output->writeln('<info>成功生成 systemd 文件,位置:' . $path . '</info>');
$output->writeln("<info>有关如何使用 systemd 配置文件,请访问 `https://github.com/zhamao-robot/zhamao-framework/issues/36`</info>"); $output->writeln('<info>有关如何使用 systemd 配置文件,请访问 `https://github.com/zhamao-robot/zhamao-framework/issues/36`</info>');
return 0; return 0;
} }
private function generate() { private function generate()
{
$s = "[Unit]\nDescription=zhamao-framework Daemon\nAfter=rc-local.service\n\n[Service]\nType=simple"; $s = "[Unit]\nDescription=zhamao-framework Daemon\nAfter=rc-local.service\n\n[Service]\nType=simple";
$s .= "\nUser=" . exec("whoami"); $s .= "\nUser=" . exec('whoami');
$s .= "\nGroup=" . exec("groups | awk '{print $1}'"); $s .= "\nGroup=" . exec("groups | awk '{print $1}'");
$s .= "\nWorkingDirectory=" . getcwd(); $s .= "\nWorkingDirectory=" . getcwd();
global $argv; global $argv;
$s .= "\nExecStart=" . PHP_BINARY . " {$argv[0]} server"; $s .= "\nExecStart=" . PHP_BINARY . " {$argv[0]} server";
$s .= "\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n"; $s .= "\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n";
@mkdir(getcwd() . "/resources/"); @mkdir(getcwd() . '/resources/');
file_put_contents(ZMConfig::get("global", "zm_data") . "zhamao.service", $s); file_put_contents(ZMConfig::get('global', 'zm_data') . 'zhamao.service', $s);
return ZMConfig::get("global", "zm_data") . "zhamao.service"; return ZMConfig::get('global', 'zm_data') . 'zhamao.service';
} }
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command; namespace ZM\Command;
@@ -11,99 +12,107 @@ use Symfony\Component\Console\Output\OutputInterface;
class InitCommand extends Command class InitCommand extends Command
{ {
private $extract_files = [
"/zhamao",
"/config/global.php",
"/.gitignore",
"/config/file_header.json",
"/config/console_color.json",
"/config/motd.txt",
"/src/Module/Example/Hello.php",
"/src/Module/Middleware/TimerMiddleware.php",
"/src/Custom/global_function.php"
];
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'init'; protected static $defaultName = 'init';
protected function configure() { private $extract_files = [
$this->setDescription("Initialize framework starter | 初始化框架运行的基础文件"); '/zhamao',
'/config/global.php',
'/.gitignore',
'/config/file_header.json',
'/config/console_color.json',
'/config/motd.txt',
'/src/Module/Example/Hello.php',
'/src/Module/Middleware/TimerMiddleware.php',
'/src/Custom/global_function.php',
];
protected function configure()
{
$this->setDescription('Initialize framework starter | 初始化框架运行的基础文件');
$this->setDefinition([ $this->setDefinition([
new InputOption("force", "F", null, "强制重制,覆盖现有文件") new InputOption('force', 'F', null, '强制重制,覆盖现有文件'),
]); ]);
$this->setHelp("此命令将会解压以下文件到项目的根目录:\n" . implode("\n", $this->getExtractFiles())); $this->setHelp("此命令将会解压以下文件到项目的根目录:\n" . implode("\n", $this->getExtractFiles()));
// ... // ...
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
if (LOAD_MODE === 1) { // 从composer依赖而来的项目模式最基本的需要初始化的模式 if (LOAD_MODE === 1) { // 从composer依赖而来的项目模式最基本的需要初始化的模式
$output->writeln("<comment>Initializing files</comment>"); $output->writeln('<comment>Initializing files</comment>');
$base_path = WORKING_DIR; $base_path = WORKING_DIR;
$args = $input->getOption("force"); $args = $input->getOption('force');
foreach ($this->extract_files as $file) { foreach ($this->extract_files as $file) {
if (!file_exists($base_path . $file) || $args) { if (!file_exists($base_path . $file) || $args) {
$info = pathinfo($file); $info = pathinfo($file);
@mkdir($base_path . $info["dirname"], 0777, true); @mkdir($base_path . $info['dirname'], 0777, true);
echo "Copying " . $file . PHP_EOL; echo 'Copying ' . $file . PHP_EOL;
$package_name = (json_decode(file_get_contents(__DIR__ . "/../../../composer.json"), true)["name"]); $package_name = (json_decode(file_get_contents(__DIR__ . '/../../../composer.json'), true)['name']);
copy($base_path . "/vendor/" . $package_name . $file, $base_path . $file); copy($base_path . '/vendor/' . $package_name . $file, $base_path . $file);
} else { } else {
echo "Skipping " . $file . " , file exists." . PHP_EOL; echo 'Skipping ' . $file . ' , file exists.' . PHP_EOL;
} }
} }
chmod($base_path . "/zhamao", 0755); chmod($base_path . '/zhamao', 0755);
$autoload = [ $autoload = [
"psr-4" => [ 'psr-4' => [
"Module\\" => "src/Module", 'Module\\' => 'src/Module',
"Custom\\" => "src/Custom" 'Custom\\' => 'src/Custom',
],
'files' => [
'src/Custom/global_function.php',
], ],
"files" => [
"src/Custom/global_function.php"
]
]; ];
if (file_exists($base_path . "/composer.json")) { if (file_exists($base_path . '/composer.json')) {
$composer = json_decode(file_get_contents($base_path . "/composer.json"), true); $composer = json_decode(file_get_contents($base_path . '/composer.json'), true);
if (!isset($composer["autoload"])) { if (!isset($composer['autoload'])) {
$composer["autoload"] = $autoload; $composer['autoload'] = $autoload;
} else { } else {
foreach ($autoload["psr-4"] as $k => $v) { foreach ($autoload['psr-4'] as $k => $v) {
if (!isset($composer["autoload"]["psr-4"][$k])) $composer["autoload"]["psr-4"][$k] = $v; if (!isset($composer['autoload']['psr-4'][$k])) {
$composer['autoload']['psr-4'][$k] = $v;
}
} }
foreach ($autoload["files"] as $v) { foreach ($autoload['files'] as $v) {
if (!in_array($v, $composer["autoload"]["files"])) $composer["autoload"]["files"][] = $v; if (!in_array($v, $composer['autoload']['files'])) {
$composer['autoload']['files'][] = $v;
}
} }
} }
file_put_contents($base_path . "/composer.json", json_encode($composer, 64 | 128 | 256)); file_put_contents($base_path . '/composer.json', json_encode($composer, 64 | 128 | 256));
$output->writeln("<info>Executing composer command: `composer dump-autoload`</info>"); $output->writeln('<info>Executing composer command: `composer dump-autoload`</info>');
exec("composer dump-autoload"); exec('composer dump-autoload');
echo PHP_EOL; echo PHP_EOL;
} else { } else {
echo(zm_internal_errcode("E00041") . "Error occurred. Please check your updates.\n"); echo zm_internal_errcode('E00041') . "Error occurred. Please check your updates.\n";
return 1; return 1;
} }
$output->writeln("<info>Done!</info>"); $output->writeln('<info>Done!</info>');
return 0; return 0;
} elseif (LOAD_MODE === 2) { //从phar启动的框架包初始化的模式 }
if (LOAD_MODE === 2) { //从phar启动的框架包初始化的模式
$phar_link = new Phar(__DIR__); $phar_link = new Phar(__DIR__);
$current_dir = pathinfo($phar_link->getPath())["dirname"]; $current_dir = pathinfo($phar_link->getPath())['dirname'];
chdir($current_dir); chdir($current_dir);
$phar_link = "phar://" . $phar_link->getPath(); $phar_link = 'phar://' . $phar_link->getPath();
foreach ($this->extract_files as $file) { foreach ($this->extract_files as $file) {
if (!file_exists($current_dir . $file)) { if (!file_exists($current_dir . $file)) {
$info = pathinfo($file); $info = pathinfo($file);
@mkdir($current_dir . $info["dirname"], 0777, true); @mkdir($current_dir . $info['dirname'], 0777, true);
echo "Copying " . $file . PHP_EOL; echo 'Copying ' . $file . PHP_EOL;
file_put_contents($current_dir . $file, file_get_contents($phar_link . $file)); file_put_contents($current_dir . $file, file_get_contents($phar_link . $file));
} else { } else {
echo "Skipping " . $file . " , file exists." . PHP_EOL; echo 'Skipping ' . $file . ' , file exists.' . PHP_EOL;
} }
} }
} }
$output->writeln(zm_internal_errcode("E00042") . "initialization must be started with composer-project mode!"); $output->writeln(zm_internal_errcode('E00042') . 'initialization must be started with composer-project mode!');
return 1; return 1;
} }
private function getExtractFiles(): array { private function getExtractFiles(): array
{
return $this->extract_files; return $this->extract_files;
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Module; namespace ZM\Command\Module;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -14,67 +14,78 @@ use ZM\Utils\Manager\ModuleManager;
class ModuleListCommand extends Command class ModuleListCommand extends Command
{ {
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'module:list'; protected static $defaultName = 'module:list';
protected function configure() { protected function configure()
$this->setDescription("查看所有模块信息"); {
$this->setHelp("此功能将会把炸毛框架的模块列举出来。"); $this->setDescription('查看所有模块信息');
$this->setHelp('此功能将会把炸毛框架的模块列举出来。');
// ... // ...
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config'); ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
ZMConfig::setEnv($args["env"] ?? ""); ZMConfig::setEnv($args['env'] ?? '');
if (ZMConfig::get("global") === false) { if (ZMConfig::get('global') === false) {
die (zm_internal_errcode("E00007") . "Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n"); exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
} }
//定义常量 //定义常量
/** @noinspection PhpIncludeInspection */ /** @noinspection PhpIncludeInspection */
include_once DataProvider::getFrameworkRootDir() . "/src/ZM/global_defines.php"; include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
Console::init( Console::init(
ZMConfig::get("global", "info_level") ?? 2, ZMConfig::get('global', 'info_level') ?? 2,
null, null,
$args["log-theme"] ?? "default", $args['log-theme'] ?? 'default',
($o = ZMConfig::get("console_color")) === false ? [] : $o ($o = ZMConfig::get('console_color')) === false ? [] : $o
); );
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai"; $timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
date_default_timezone_set($timezone); date_default_timezone_set($timezone);
$list = ModuleManager::getConfiguredModules(); $list = ModuleManager::getConfiguredModules();
foreach ($list as $v) { foreach ($list as $v) {
echo "[" . Console::setColor($v["name"], "green") . "]" . PHP_EOL; echo '[' . Console::setColor($v['name'], 'green') . ']' . PHP_EOL;
$out_list = ["类型" => "源码(source)"]; $out_list = ['类型' => '源码(source)'];
if (isset($v["version"])) $out_list["版本"] = $v["version"]; if (isset($v['version'])) {
if (isset($v["description"])) $out_list["描述"] = $v["description"]; $out_list['版本'] = $v['version'];
$out_list["目录"] = str_replace(DataProvider::getSourceRootDir() . "/", "", $v["module-path"]); }
if (isset($v['description'])) {
$out_list['描述'] = $v['description'];
}
$out_list['目录'] = str_replace(DataProvider::getSourceRootDir() . '/', '', $v['module-path']);
$this->printList($out_list); $this->printList($out_list);
} }
if ($list === []) { if ($list === []) {
echo Console::setColor("没有发现已编写打包配置文件zm.json的模块", "yellow") . PHP_EOL; echo Console::setColor('没有发现已编写打包配置文件zm.json的模块', 'yellow') . PHP_EOL;
} }
$list = ModuleManager::getPackedModules(); $list = ModuleManager::getPackedModules();
foreach ($list as $v) { foreach ($list as $v) {
echo "[" . Console::setColor($v["name"], "gold") . "]" . PHP_EOL; echo '[' . Console::setColor($v['name'], 'gold') . ']' . PHP_EOL;
$out_list = ["类型" => "模块包(phar)"]; $out_list = ['类型' => '模块包(phar)'];
if (isset($v["module-config"]["version"])) $out_list["版本"] = $v["module-config"]["version"]; if (isset($v['module-config']['version'])) {
if (isset($v["module-config"]["description"])) $out_list["描述"] = $v["module-config"]["description"]; $out_list['版本'] = $v['module-config']['version'];
$out_list["位置"] = str_replace(DataProvider::getSourceRootDir() . "/", "", $v["phar-path"]); }
if (isset($v['module-config']['description'])) {
$out_list['描述'] = $v['module-config']['description'];
}
$out_list['位置'] = str_replace(DataProvider::getSourceRootDir() . '/', '', $v['phar-path']);
$this->printList($out_list); $this->printList($out_list);
} }
if ($list === []) { if ($list === []) {
echo Console::setColor("没有发现已打包且装载的模块!", "yellow") . PHP_EOL; echo Console::setColor('没有发现已打包且装载的模块!', 'yellow') . PHP_EOL;
} }
return 0; return 0;
} }
private function printList($list) { private function printList($list)
{
foreach ($list as $k => $v) { foreach ($list as $k => $v) {
echo "\t" . $k . ": " . Console::setColor($v, "yellow") . PHP_EOL; echo "\t" . $k . ': ' . Console::setColor($v, 'yellow') . PHP_EOL;
} }
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Module; namespace ZM\Command\Module;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -19,42 +19,47 @@ class ModulePackCommand extends Command
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'module:pack'; protected static $defaultName = 'module:pack';
protected function configure() { protected function configure()
$this->addArgument("module-name", InputArgument::REQUIRED); {
$this->setDescription("将配置好的模块构建一个phar包"); $this->addArgument('module-name', InputArgument::REQUIRED);
$this->setHelp("此功能将会把炸毛框架的模块打包为\".phar\",供发布和执行。"); $this->setDescription('将配置好的模块构建一个phar包');
$this->addOption("target", "D", InputOption::VALUE_REQUIRED, "Output Directory | 指定输出目录"); $this->setHelp('此功能将会把炸毛框架的模块打包为".phar",供发布和执行。');
$this->addOption('target', 'D', InputOption::VALUE_REQUIRED, 'Output Directory | 指定输出目录');
// ... // ...
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config'); ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
ZMConfig::setEnv($args["env"] ?? ""); ZMConfig::setEnv($args['env'] ?? '');
if (ZMConfig::get("global") === false) { if (ZMConfig::get('global') === false) {
die (zm_internal_errcode("E00007") . "Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n"); exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
} }
//定义常量 //定义常量
include_once DataProvider::getFrameworkRootDir()."/src/ZM/global_defines.php"; include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
Console::init( Console::init(
ZMConfig::get("global", "info_level") ?? 2, ZMConfig::get('global', 'info_level') ?? 2,
null, null,
$args["log-theme"] ?? "default", $args['log-theme'] ?? 'default',
($o = ZMConfig::get("console_color")) === false ? [] : $o ($o = ZMConfig::get('console_color')) === false ? [] : $o
); );
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai"; $timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
date_default_timezone_set($timezone); date_default_timezone_set($timezone);
$list = ModuleManager::getConfiguredModules(); $list = ModuleManager::getConfiguredModules();
if (!isset($list[$input->getArgument("module-name")])) { if (!isset($list[$input->getArgument('module-name')])) {
$output->writeln("<error>不存在模块 ".$input->getArgument("module-name")." !</error>"); $output->writeln('<error>不存在模块 ' . $input->getArgument('module-name') . ' !</error>');
return 1; return 1;
} }
$result = ModuleManager::packModule($list[$input->getArgument("module-name")], $input->getOption("target")); $result = ModuleManager::packModule($list[$input->getArgument('module-name')], $input->getOption('target'));
if ($result) Console::success("打包完成!"); if ($result) {
else Console::error("打包失败!"); Console::success('打包完成!');
} else {
Console::error('打包失败!');
}
return 0; return 0;
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Module; namespace ZM\Command\Module;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -16,51 +16,56 @@ use ZM\Utils\Manager\ModuleManager;
class ModuleUnpackCommand extends Command class ModuleUnpackCommand extends Command
{ {
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'module:unpack'; protected static $defaultName = 'module:unpack';
protected function configure() { protected function configure()
{
$this->setDefinition([ $this->setDefinition([
new InputArgument("module-name", InputArgument::REQUIRED), new InputArgument('module-name', InputArgument::REQUIRED),
new InputOption("overwrite-light-cache", null, null, "覆盖现有的LightCache项目"), new InputOption('overwrite-light-cache', null, null, '覆盖现有的LightCache项目'),
new InputOption("overwrite-zm-data", null, null, "覆盖现有的zm_data文件"), new InputOption('overwrite-zm-data', null, null, '覆盖现有的zm_data文件'),
new InputOption("overwrite-source", null, null, "覆盖现有的源码文件"), new InputOption('overwrite-source', null, null, '覆盖现有的源码文件'),
new InputOption("ignore-depends", null, null, "解包时忽略检查依赖") new InputOption('ignore-depends', null, null, '解包时忽略检查依赖'),
]); ]);
$this->setDescription("解包一个phar模块到src目录"); $this->setDescription('解包一个phar模块到src目录');
$this->setHelp("此功能将phar格式的模块包解包到src目录下。"); $this->setHelp('此功能将phar格式的模块包解包到src目录下。');
// ... // ...
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config'); ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
ZMConfig::setEnv($args["env"] ?? ""); ZMConfig::setEnv($args['env'] ?? '');
if (ZMConfig::get("global") === false) { if (ZMConfig::get('global') === false) {
die (zm_internal_errcode("E00007") . "Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n"); exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
} }
//定义常量 //定义常量
/** @noinspection PhpIncludeInspection */ /** @noinspection PhpIncludeInspection */
include_once DataProvider::getFrameworkRootDir()."/src/ZM/global_defines.php"; include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
Console::init( Console::init(
ZMConfig::get("global", "info_level") ?? 4, ZMConfig::get('global', 'info_level') ?? 4,
null, null,
$args["log-theme"] ?? "default", $args['log-theme'] ?? 'default',
($o = ZMConfig::get("console_color")) === false ? [] : $o ($o = ZMConfig::get('console_color')) === false ? [] : $o
); );
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai"; $timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
date_default_timezone_set($timezone); date_default_timezone_set($timezone);
$list = ModuleManager::getPackedModules(); $list = ModuleManager::getPackedModules();
if (!isset($list[$input->getArgument("module-name")])) { if (!isset($list[$input->getArgument('module-name')])) {
$output->writeln("<error>不存在打包的模块 ".$input->getArgument("module-name")." !</error>"); $output->writeln('<error>不存在打包的模块 ' . $input->getArgument('module-name') . ' !</error>');
return 1; return 1;
} }
$result = ModuleManager::unpackModule($list[$input->getArgument("module-name")], $input->getOptions()); $result = ModuleManager::unpackModule($list[$input->getArgument('module-name')], $input->getOptions());
if ($result) Console::success("解压完成!"); if ($result) {
else Console::error("解压失败!"); Console::success('解压完成!');
} else {
Console::error('解压失败!');
}
return 0; return 0;
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command; namespace ZM\Command;
use Swoole\Atomic; use Swoole\Atomic;
use Swoole\Http\Request; use Swoole\Http\Request;
use Swoole\Http\Response; use Swoole\Http\Response;
@@ -26,71 +26,74 @@ class PureHttpCommand extends Command
// the name of the command (the part after "bin/console") // the name of the command (the part after "bin/console")
protected static $defaultName = 'simple-http-server'; protected static $defaultName = 'simple-http-server';
protected function configure() { protected function configure()
$this->setDescription("Run a simple http server | 启动一个简单的文件 HTTP 服务器"); {
$this->setHelp("直接运行可以启动"); $this->setDescription('Run a simple http server | 启动一个简单的文件 HTTP 服务器');
$this->setHelp('直接运行可以启动');
$this->addArgument('dir', InputArgument::REQUIRED, 'Your directory'); $this->addArgument('dir', InputArgument::REQUIRED, 'Your directory');
$this->addOption("host", 'H', InputOption::VALUE_REQUIRED, "启动监听地址"); $this->addOption('host', 'H', InputOption::VALUE_REQUIRED, '启动监听地址');
$this->addOption("port", 'P', InputOption::VALUE_REQUIRED, "启动监听地址的端口"); $this->addOption('port', 'P', InputOption::VALUE_REQUIRED, '启动监听地址的端口');
// ... // ...
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
$tty_width = explode(" ", trim(exec("stty size")))[1]; {
$tty_width = explode(' ', trim(exec('stty size')))[1];
if (realpath($input->getArgument('dir') ?? '.') === false) { if (realpath($input->getArgument('dir') ?? '.') === false) {
$output->writeln("<error>Directory error(" . ($input->getArgument('dir') ?? '.') . "): no such file or directory.</error>"); $output->writeln('<error>Directory error(' . ($input->getArgument('dir') ?? '.') . '): no such file or directory.</error>');
return self::FAILURE; return self::FAILURE;
} }
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config'); ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
$global = ZMConfig::get("global"); $global = ZMConfig::get('global');
$host = $input->getOption("host") ?? $global["host"]; $host = $input->getOption('host') ?? $global['host'];
$port = $input->getOption("port") ?? $global["port"]; $port = $input->getOption('port') ?? $global['port'];
$index = ["index.html", "index.htm"]; $index = ['index.html', 'index.htm'];
$out = [ $out = [
"listen" => $host.":".$port, 'listen' => $host . ':' . $port,
"version" => ZM_VERSION, 'version' => ZM_VERSION,
"web_root" => realpath($input->getArgument('dir') ?? '.'), 'web_root' => realpath($input->getArgument('dir') ?? '.'),
"index" => implode(",", $index) 'index' => implode(',', $index),
]; ];
Framework::printProps($out, $tty_width); Framework::printProps($out, $tty_width);
$server = new Server($host, $port); $server = new Server($host, $port);
$server->set(ZMConfig::get("global", "swoole")); $server->set(ZMConfig::get('global', 'swoole'));
Console::init(2, $server); Console::init(2, $server);
ZMAtomic::$atomics["request"] = []; ZMAtomic::$atomics['request'] = [];
for ($i = 0; $i < 32; ++$i) { for ($i = 0; $i < 32; ++$i) {
ZMAtomic::$atomics["request"][$i] = new Atomic(0); ZMAtomic::$atomics['request'][$i] = new Atomic(0);
} }
$server->on("request", function (Request $request, Response $response) use ($input, $index, $server) { $server->on('request', function (Request $request, Response $response) use ($input, $index, $server) {
ZMAtomic::$atomics["request"][$server->worker_id]->add(1); ZMAtomic::$atomics['request'][$server->worker_id]->add(1);
HttpUtil::handleStaticPage( HttpUtil::handleStaticPage(
$request->server["request_uri"], $request->server['request_uri'],
$response, $response,
[ [
"document_root" => realpath($input->getArgument('dir') ?? '.'), 'document_root' => realpath($input->getArgument('dir') ?? '.'),
"document_index" => $index 'document_index' => $index,
]); ]
);
//echo "\r" . Coroutine::stats()["coroutine_peak_num"]; //echo "\r" . Coroutine::stats()["coroutine_peak_num"];
}); });
$server->on("start", function ($server) { $server->on('start', function ($server) {
Process::signal(SIGINT, function () use ($server) { Process::signal(SIGINT, function () use ($server) {
echo "\r"; echo "\r";
Console::warning("Server interrupted by keyboard."); Console::warning('Server interrupted by keyboard.');
for ($i = 0; $i < 32; ++$i) { for ($i = 0; $i < 32; ++$i) {
$num = ZMAtomic::$atomics["request"][$i]->get(); $num = ZMAtomic::$atomics['request'][$i]->get();
if ($num != 0) if ($num != 0) {
echo "[$i]: " . $num . "\n"; echo "[{$i}]: " . $num . "\n";
}
} }
$server->shutdown(); $server->shutdown();
$server->stop(); $server->stop();
}); });
Console::success("Server started. Use Ctrl+C to stop."); Console::success('Server started. Use Ctrl+C to stop.');
}); });
$server->start(); $server->start();
// return this if there was no problem running the command // return this if there was no problem running the command
// (it's equivalent to returning int(0)) // (it's equivalent to returning int(0))
return 0; return 0;
// or return this if some error happened during the execution // or return this if some error happened during the execution
// (it's equivalent to returning int(1)) // (it's equivalent to returning int(1))
// return 1; // return 1;

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command; namespace ZM\Command;
@@ -8,61 +9,63 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use ZM\Framework; use ZM\Framework;
use ZM\Utils\DataProvider;
class RunServerCommand extends Command class RunServerCommand extends Command
{ {
protected static $defaultName = 'server'; protected static $defaultName = 'server';
protected function configure() { public static function exportDefinition()
$this->setAliases(['server:start']); {
$this->setDefinition([ $cmd = new self();
new InputOption("debug-mode", "D", null, "开启调试模式 (这将关闭协程化)"), $cmd->configure();
new InputOption("log-debug", null, null, "调整消息等级到debug (log-level=4)"), return $cmd->getDefinition();
new InputOption("log-verbose", null, null, "调整消息等级到verbose (log-level=3)"),
new InputOption("log-info", null, null, "调整消息等级到info (log-level=2)"),
new InputOption("log-warning", null, null, "调整消息等级到warning (log-level=1)"),
new InputOption("log-error", null, null, "调整消息等级到error (log-level=0)"),
new InputOption("log-theme", null, InputOption::VALUE_REQUIRED, "改变终端的主题配色"),
new InputOption("disable-console-input", null, null, "禁止终端输入内容 (废弃)"),
new InputOption("interact", null, null, "打开终端输入"),
new InputOption("remote-terminal", null, null, "启用远程终端配置使用global.php中的"),
new InputOption("disable-coroutine", null, null, "关闭协程Hook"),
new InputOption("daemon", null, null, "以守护进程的方式运行框架"),
new InputOption("worker-num", null, InputOption::VALUE_REQUIRED, "启动框架时运行的 Worker 进程数量"),
new InputOption("task-worker-num", null, InputOption::VALUE_REQUIRED, "启动框架时运行的 TaskWorker 进程数量"),
new InputOption("watch", null, null, "监听 src/ 目录的文件变化并热更新"),
new InputOption("show-php-ver", null, null, "启动时显示PHP和Swoole版本"),
new InputOption("env", null, InputOption::VALUE_REQUIRED, "设置环境类型 (production, development, staging)"),
new InputOption("disable-safe-exit", null, null, "关闭安全退出关闭后按CtrlC时直接杀死进程"),
new InputOption("preview", null, null, "只显示参数,不启动服务器"),
new InputOption("force-load-module", null, InputOption::VALUE_OPTIONAL, "强制打包状态下加载模块(使用英文逗号分割多个)"),
new InputOption("polling-watch", null, null, "强制启用轮询模式监听"),
]);
$this->setDescription("Run zhamao-framework | 启动框架");
$this->setHelp("直接运行可以启动");
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function configure()
if (($opt = $input->getOption("env")) !== null) { {
if (!in_array($opt, ["production", "staging", "development", ""])) { $this->setAliases(['server:start']);
$output->writeln("<error> \"--env\" option only accept production, development, staging and [empty] ! </error>"); $this->setDefinition([
new InputOption('debug-mode', 'D', null, '开启调试模式 (这将关闭协程化)'),
new InputOption('log-debug', null, null, '调整消息等级到debug (log-level=4)'),
new InputOption('log-verbose', null, null, '调整消息等级到verbose (log-level=3)'),
new InputOption('log-info', null, null, '调整消息等级到info (log-level=2)'),
new InputOption('log-warning', null, null, '调整消息等级到warning (log-level=1)'),
new InputOption('log-error', null, null, '调整消息等级到error (log-level=0)'),
new InputOption('log-theme', null, InputOption::VALUE_REQUIRED, '改变终端的主题配色'),
new InputOption('disable-console-input', null, null, '禁止终端输入内容 (废弃)'),
new InputOption('interact', null, null, '打开终端输入'),
new InputOption('remote-terminal', null, null, '启用远程终端配置使用global.php中的'),
new InputOption('disable-coroutine', null, null, '关闭协程Hook'),
new InputOption('daemon', null, null, '以守护进程的方式运行框架'),
new InputOption('worker-num', null, InputOption::VALUE_REQUIRED, '启动框架时运行的 Worker 进程数量'),
new InputOption('task-worker-num', null, InputOption::VALUE_REQUIRED, '启动框架时运行的 TaskWorker 进程数量'),
new InputOption('watch', null, null, '监听 src/ 目录的文件变化并热更新'),
new InputOption('show-php-ver', null, null, '启动时显示PHP和Swoole版本'),
new InputOption('env', null, InputOption::VALUE_REQUIRED, '设置环境类型 (production, development, staging)'),
new InputOption('disable-safe-exit', null, null, '关闭安全退出关闭后按CtrlC时直接杀死进程'),
new InputOption('preview', null, null, '只显示参数,不启动服务器'),
new InputOption('force-load-module', null, InputOption::VALUE_OPTIONAL, '强制打包状态下加载模块(使用英文逗号分割多个)'),
new InputOption('polling-watch', null, null, '强制启用轮询模式监听'),
]);
$this->setDescription('Run zhamao-framework | 启动框架');
$this->setHelp('直接运行可以启动');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (($opt = $input->getOption('env')) !== null) {
if (!in_array($opt, ['production', 'staging', 'development', ''])) {
$output->writeln('<error> "--env" option only accept production, development, staging and [empty] ! </error>');
return 1; return 1;
} }
} }
$state = Framework::getProcessState(ZM_PROCESS_MASTER); $state = Framework::getProcessState(ZM_PROCESS_MASTER);
if (is_array($state) && posix_getsid($state['pid'] ?? -1) !== false) { if (is_array($state) && posix_getsid($state['pid'] ?? -1) !== false) {
$output->writeln("<error>检测到已经在 pid: {$state['pid']} 进程启动了框架!</error>"); $output->writeln("<error>检测到已经在 pid: {$state['pid']} 进程启动了框架!</error>");
$output->writeln("<error>不可以同时启动两个框架!</error>"); $output->writeln('<error>不可以同时启动两个框架!</error>');
return 1; return 1;
} }
(new Framework($input->getOptions()))->start(); (new Framework($input->getOptions()))->start();
return 0; return 0;
} }
public static function exportDefinition() {
$cmd = new self();
$cmd->configure();
return $cmd->getDefinition();
}
} }

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Server; namespace ZM\Command\Server;
@@ -12,14 +13,16 @@ class ServerReloadCommand extends DaemonCommand
{ {
protected static $defaultName = 'server:reload'; protected static $defaultName = 'server:reload';
protected function configure() { protected function configure()
$this->setDescription("重载框架"); {
$this->setDescription('重载框架');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output); parent::execute($input, $output);
Process::kill(intval($this->daemon_file["pid"]), SIGUSR1); Process::kill(intval($this->daemon_file['pid']), SIGUSR1);
$output->writeln("<info>成功重载!</info>"); $output->writeln('<info>成功重载!</info>');
return 0; return 0;
} }
} }

View File

@@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Server; namespace ZM\Command\Server;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -10,25 +12,25 @@ class ServerStatusCommand extends DaemonCommand
{ {
protected static $defaultName = 'server:status'; protected static $defaultName = 'server:status';
protected function configure() { protected function configure()
$this->setDescription("查看框架的运行状态"); {
$this->setDescription('查看框架的运行状态');
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output); parent::execute($input, $output);
$output->writeln("<info>框架" . ($this->daemon_file["daemon"] ? "以守护进程模式" : "") . "运行中pid" . $this->daemon_file["pid"] . "</info>"); $output->writeln('<info>框架' . ($this->daemon_file['daemon'] ? '以守护进程模式' : '') . '运行中pid' . $this->daemon_file['pid'] . '</info>');
if ($this->daemon_file["daemon"]) { if ($this->daemon_file['daemon']) {
$output->writeln("<comment>----- 以下是stdout内容 -----</comment>"); $output->writeln('<comment>----- 以下是stdout内容 -----</comment>');
$stdout = file_get_contents($this->daemon_file["stdout"]); $stdout = file_get_contents($this->daemon_file['stdout']);
$stdout = explode("\n", $stdout); $stdout = explode("\n", $stdout);
for ($i = 15; $i > 0; --$i) { for ($i = 15; $i > 0; --$i) {
if (isset($stdout[count($stdout) - $i])) if (isset($stdout[count($stdout) - $i])) {
echo $stdout[count($stdout) - $i] . PHP_EOL; echo $stdout[count($stdout) - $i] . PHP_EOL;
}
} }
} }
return 0; return 0;
} }
} }
{
}

View File

@@ -1,5 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Command\Server; namespace ZM\Command\Server;
@@ -15,42 +16,44 @@ class ServerStopCommand extends DaemonCommand
{ {
protected static $defaultName = 'server:stop'; protected static $defaultName = 'server:stop';
protected function configure() { protected function configure()
$this->setDescription("停止运行的框架"); {
$this->setDescription('停止运行的框架');
$this->setDefinition([ $this->setDefinition([
new InputOption('force', 'f', InputOption::VALUE_NONE, '强制停止'), new InputOption('force', 'f', InputOption::VALUE_NONE, '强制停止'),
]); ]);
} }
protected function execute(InputInterface $input, OutputInterface $output): int { protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->getOption('force') !== false) { if ($input->getOption('force') !== false) {
$file_path = _zm_pid_dir(); $file_path = _zm_pid_dir();
$list = DataProvider::scanDirFiles($file_path, false, true); $list = DataProvider::scanDirFiles($file_path, false, true);
foreach($list as $file) { foreach ($list as $file) {
$name = explode('.', $file); $name = explode('.', $file);
if (end($name) == 'pid') { if (end($name) == 'pid') {
$pid = file_get_contents($file_path.'/'.$file); $pid = file_get_contents($file_path . '/' . $file);
Process::kill($pid, SIGKILL); Process::kill($pid, SIGKILL);
} elseif ($file === 'master.json') { } elseif ($file === 'master.json') {
$json = json_decode(file_get_contents($file_path.'/'.$file), true); $json = json_decode(file_get_contents($file_path . '/' . $file), true);
Process::kill($json['pid'], SIGKILL); Process::kill($json['pid'], SIGKILL);
} }
unlink($file_path.'/'.$file); unlink($file_path . '/' . $file);
} }
} else { } else {
parent::execute($input, $output); parent::execute($input, $output);
} }
Process::kill(intval($this->daemon_file["pid"]), SIGTERM); Process::kill(intval($this->daemon_file['pid']), SIGTERM);
$i = 10; $i = 10;
while (Framework::getProcessState(ZM_PROCESS_MASTER) !== false && $i > 0) { while (Framework::getProcessState(ZM_PROCESS_MASTER) !== false && $i > 0) {
sleep(1); sleep(1);
--$i; --$i;
} }
if ($i === 0) { if ($i === 0) {
$output->writeln("<error>停止失败请检查进程pid #" . $this->daemon_file["pid"] . " 是否响应!</error>"); $output->writeln('<error>停止失败请检查进程pid #' . $this->daemon_file['pid'] . ' 是否响应!</error>');
$output->writeln("<error>或者可以尝试使用参数 --force 来强行杀死所有进程</error>"); $output->writeln('<error>或者可以尝试使用参数 --force 来强行杀死所有进程</error>');
} else { } else {
$output->writeln("<info>成功停止!</info>"); $output->writeln('<info>成功停止!</info>');
} }
return 0; return 0;
} }

View File

@@ -1,11 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace ZM; namespace ZM;
use Exception; use Exception;
use Phar; use Phar;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Command\BuildCommand; use ZM\Command\BuildCommand;
use ZM\Command\CheckConfigCommand; use ZM\Command\CheckConfigCommand;
use ZM\Command\Daemon\DaemonReloadCommand; use ZM\Command\Daemon\DaemonReloadCommand;
@@ -18,9 +21,6 @@ use ZM\Command\Module\ModulePackCommand;
use ZM\Command\Module\ModuleUnpackCommand; use ZM\Command\Module\ModuleUnpackCommand;
use ZM\Command\PureHttpCommand; use ZM\Command\PureHttpCommand;
use ZM\Command\RunServerCommand; use ZM\Command\RunServerCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Command\Server\ServerReloadCommand; use ZM\Command\Server\ServerReloadCommand;
use ZM\Command\Server\ServerStatusCommand; use ZM\Command\Server\ServerStatusCommand;
use ZM\Command\Server\ServerStopCommand; use ZM\Command\Server\ServerStopCommand;
@@ -28,29 +28,34 @@ use ZM\Exception\InitException;
class ConsoleApplication extends Application class ConsoleApplication extends Application
{ {
private static $obj = null; public const VERSION_ID = 436;
const VERSION_ID = 435; public const VERSION = '2.7.0-beta2';
const VERSION = "2.7.0-beta1";
private static $obj;
/** /**
* @throws InitException * @throws InitException
*/ */
public function __construct(string $name = 'UNKNOWN') { public function __construct(string $name = 'UNKNOWN')
if (self::$obj !== null) throw new InitException(zm_internal_errcode("E00069") . "Initializing another Application is not allowed!"); {
define("ZM_VERSION_ID", self::VERSION_ID); if (self::$obj !== null) {
define("ZM_VERSION", self::VERSION); throw new InitException(zm_internal_errcode('E00069') . 'Initializing another Application is not allowed!');
}
define('ZM_VERSION_ID', self::VERSION_ID);
define('ZM_VERSION', self::VERSION);
self::$obj = $this; self::$obj = $this;
parent::__construct($name, ZM_VERSION); parent::__construct($name, ZM_VERSION);
} }
/** /**
* @param string $with_default_cmd
* @return ConsoleApplication
* @throws InitException * @throws InitException
*/ */
public function initEnv(string $with_default_cmd = ""): ConsoleApplication { public function initEnv(string $with_default_cmd = ''): ConsoleApplication
if (defined("WORKING_DIR")) throw new InitException(); {
if (defined('WORKING_DIR')) {
throw new InitException();
}
_zm_env_check(); _zm_env_check();
@@ -61,22 +66,21 @@ class ConsoleApplication extends Application
define('ZM_PROCESS_USER', 8); define('ZM_PROCESS_USER', 8);
define('ZM_PROCESS_TASKWORKER', 16); define('ZM_PROCESS_TASKWORKER', 16);
define("WORKING_DIR", getcwd()); define('WORKING_DIR', getcwd());
if (!is_dir(_zm_pid_dir())) { if (!is_dir(_zm_pid_dir())) {
@mkdir(_zm_pid_dir()); @mkdir(_zm_pid_dir());
} }
if (Phar::running() !== "") { if (Phar::running() !== '') {
echo "* Running in phar mode.\n"; echo "* Running in phar mode.\n";
define("SOURCE_ROOT_DIR", Phar::running()); define('SOURCE_ROOT_DIR', Phar::running());
define("LOAD_MODE", is_dir(SOURCE_ROOT_DIR . "/src/ZM") ? 0 : 1); define('LOAD_MODE', is_dir(SOURCE_ROOT_DIR . '/src/ZM') ? 0 : 1);
define("FRAMEWORK_ROOT_DIR", LOAD_MODE == 1 ? (SOURCE_ROOT_DIR . "/vendor/zhamao/framework") : SOURCE_ROOT_DIR); define('FRAMEWORK_ROOT_DIR', LOAD_MODE == 1 ? (SOURCE_ROOT_DIR . '/vendor/zhamao/framework') : SOURCE_ROOT_DIR);
} else { } else {
define("SOURCE_ROOT_DIR", WORKING_DIR); define('SOURCE_ROOT_DIR', WORKING_DIR);
define("LOAD_MODE", is_dir(SOURCE_ROOT_DIR . "/src/ZM") ? 0 : 1); define('LOAD_MODE', is_dir(SOURCE_ROOT_DIR . '/src/ZM') ? 0 : 1);
define("FRAMEWORK_ROOT_DIR", realpath(__DIR__ . "/../../")); define('FRAMEWORK_ROOT_DIR', realpath(__DIR__ . '/../../'));
} }
$this->addCommands([ $this->addCommands([
@@ -88,12 +92,12 @@ class ConsoleApplication extends Application
new ServerStopCommand(), new ServerStopCommand(),
new ServerReloadCommand(), new ServerReloadCommand(),
new PureHttpCommand(), //纯HTTP服务器指令 new PureHttpCommand(), //纯HTTP服务器指令
new SystemdGenerateCommand() new SystemdGenerateCommand(),
]); ]);
if (LOAD_MODE === 1) { if (LOAD_MODE === 1) {
$this->add(new CheckConfigCommand()); $this->add(new CheckConfigCommand());
} }
if (Phar::running() === "") { if (Phar::running() === '') {
$this->add(new BuildCommand()); $this->add(new BuildCommand());
$this->add(new InitCommand()); $this->add(new InitCommand());
$this->add(new ModulePackCommand()); $this->add(new ModulePackCommand());
@@ -106,16 +110,13 @@ class ConsoleApplication extends Application
return $this; return $this;
} }
/** public function run(InputInterface $input = null, OutputInterface $output = null): int
* @param InputInterface|null $input {
* @param OutputInterface|null $output
* @return int
*/
public function run(InputInterface $input = null, OutputInterface $output = null): int {
try { try {
return parent::run($input, $output); return parent::run($input, $output);
} catch (Exception $e) { } catch (Exception $e) {
die(zm_internal_errcode("E00005") . "{$e->getMessage()} at {$e->getFile()}({$e->getLine()})"); echo zm_internal_errcode('E00005') . "{$e->getMessage()} at {$e->getFile()}({$e->getLine()})" . PHP_EOL;
exit(1);
} }
} }
} }

View File

@@ -1,14 +1,15 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Context; namespace ZM\Context;
use Exception; use Exception;
use Swoole\Coroutine; use Swoole\Coroutine;
use Swoole\Http\Request; use Swoole\Http\Request;
use Swoole\WebSocket\Frame; use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server; use Swoole\WebSocket\Server;
use ZM\API\ZMRobot;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ConnectionObject; use ZM\ConnectionManager\ConnectionObject;
use ZM\ConnectionManager\ManagerGM; use ZM\ConnectionManager\ManagerGM;
@@ -18,194 +19,252 @@ use ZM\Exception\InterruptException;
use ZM\Exception\InvalidArgumentException; use ZM\Exception\InvalidArgumentException;
use ZM\Exception\WaitTimeoutException; use ZM\Exception\WaitTimeoutException;
use ZM\Http\Response; use ZM\Http\Response;
use ZM\API\ZMRobot;
use ZM\Utils\CoMessage; use ZM\Utils\CoMessage;
use ZM\Utils\MessageUtil; use ZM\Utils\MessageUtil;
class Context implements ContextInterface class Context implements ContextInterface
{ {
public static $context = []; public static $context = [];
private $cid; private $cid;
public function __construct($cid) { $this->cid = $cid; } public function __construct($cid)
{
$this->cid = $cid;
}
/** /**
* @return Server * @return Server
*/ */
public function getServer(): ?Server { return self::$context[$this->cid]["server"] ?? server(); } public function getServer(): ?Server
{
return self::$context[$this->cid]['server'] ?? server();
}
/** public function getFrame(): ?Frame
* @return Frame|null {
*/ return self::$context[$this->cid]['frame'] ?? null;
public function getFrame(): ?Frame { return self::$context[$this->cid]["frame"] ?? null; } }
public function getFd(): ?int { return self::$context[$this->cid]["fd"] ?? $this->getFrame()->fd ?? null; } public function getFd(): ?int
{
return self::$context[$this->cid]['fd'] ?? $this->getFrame()->fd ?? null;
}
/** /**
* @return mixed * @return mixed
*/ */
public function getData() { return self::$context[$this->cid]["data"] ?? null; } public function getData()
{
return self::$context[$this->cid]['data'] ?? null;
}
public function setData($data) { self::$context[$this->cid]["data"] = $data; } public function setData($data)
{
self::$context[$this->cid]['data'] = $data;
}
/** public function getRequest(): ?Request
* @return Request|null {
*/ return self::$context[$this->cid]['request'] ?? null;
public function getRequest(): ?Request { return self::$context[$this->cid]["request"] ?? null; } }
/** public function getResponse(): ?Response
* @return Response|null {
*/ return self::$context[$this->cid]['response'] ?? null;
public function getResponse(): ?Response { return self::$context[$this->cid]["response"] ?? null; } }
/** @return ConnectionObject|null */ public function getConnection(): ?ConnectionObject
public function getConnection(): ?ConnectionObject { return ManagerGM::get($this->getFd()); } {
return ManagerGM::get($this->getFd());
}
/** public function getCid(): ?int
* @return int|null {
*/ return $this->cid;
public function getCid(): ?int { return $this->cid; } }
/** public function getRobot(): ?ZMRobot
* @return ZMRobot|null {
*/
public function getRobot(): ?ZMRobot {
$conn = ManagerGM::get($this->getFrame()->fd); $conn = ManagerGM::get($this->getFrame()->fd);
return $conn instanceof ConnectionObject ? new ZMRobot($conn) : null; return $conn instanceof ConnectionObject ? new ZMRobot($conn) : null;
} }
public function getMessage() { public function getMessage()
if ((ZMConfig::get("global", "onebot")["message_convert_string"] ?? true) === true && is_array($msg = $this->getOriginMessage())) { {
if ((ZMConfig::get('global', 'onebot')['message_convert_string'] ?? true) === true && is_array($msg = $this->getOriginMessage())) {
return MessageUtil::arrayToStr($msg); return MessageUtil::arrayToStr($msg);
} else {
return self::$context[$this->cid]["data"]["message"] ?? null;
} }
return self::$context[$this->cid]['data']['message'] ?? null;
} }
public function setMessage($msg) { public function setMessage($msg)
{
if (is_string($msg) && is_array($this->getOriginMessage())) { if (is_string($msg) && is_array($this->getOriginMessage())) {
$msg = MessageUtil::strToArray($msg); $msg = MessageUtil::strToArray($msg);
} }
self::$context[$this->cid]["data"]["message"] = $msg; self::$context[$this->cid]['data']['message'] = $msg;
} }
public function getUserId() { return $this->getData()["user_id"] ?? null; } public function getUserId()
{
return $this->getData()['user_id'] ?? null;
}
public function setUserId($id) { self::$context[$this->cid]["data"]["user_id"] = $id; } public function setUserId($id)
{
self::$context[$this->cid]['data']['user_id'] = $id;
}
public function getGroupId() { return $this->getData()["group_id"] ?? null; } public function getGroupId()
{
return $this->getData()['group_id'] ?? null;
}
public function setGroupId($id) { self::$context[$this->cid]["data"]["group_id"] = $id; } public function setGroupId($id)
{
self::$context[$this->cid]['data']['group_id'] = $id;
}
public function getDiscussId() { return $this->getData()["discuss_id"] ?? null; } public function getDiscussId()
{
return $this->getData()['discuss_id'] ?? null;
}
public function setDiscussId($id) { self::$context[$this->cid]["data"]["discuss_id"] = $id; } public function setDiscussId($id)
{
self::$context[$this->cid]['data']['discuss_id'] = $id;
}
public function getMessageType(): ?string { return $this->getData()["message_type"] ?? null; } public function getMessageType(): ?string
{
return $this->getData()['message_type'] ?? null;
}
public function setMessageType($type) { self::$context[$this->cid]["data"]["message_type"] = $type; } public function setMessageType($type)
{
self::$context[$this->cid]['data']['message_type'] = $type;
}
public function getRobotId() { return $this->getData()["self_id"] ?? null; } public function getRobotId()
{
return $this->getData()['self_id'] ?? null;
}
public function getCache($key) { return self::$context[$this->cid]["cache"][$key] ?? null; } public function getCache($key)
{
return self::$context[$this->cid]['cache'][$key] ?? null;
}
public function setCache($key, $value) { self::$context[$this->cid]["cache"][$key] = $value; } public function setCache($key, $value)
{
self::$context[$this->cid]['cache'][$key] = $value;
}
public function getCQResponse() { return self::$context[$this->cid]["cq_response"] ?? null; } public function getCQResponse()
{
return self::$context[$this->cid]['cq_response'] ?? null;
}
/** /**
* only can used by cq->message event function * only can used by cq->message event function
* @param $msg * @param $msg
* @param bool $yield * @param bool $yield
* @return array|bool * @return array|bool
*/ */
public function reply($msg, $yield = false) { public function reply($msg, $yield = false)
{
$data = $this->getData(); $data = $this->getData();
$conn = $this->getConnection(); $conn = $this->getConnection();
if (!is_array($msg)) { if (!is_array($msg)) {
switch ($this->getData()["message_type"]) { switch ($this->getData()['message_type']) {
case "group": case 'group':
case "private": case 'private':
case "discuss": case 'discuss':
$this->setCache("has_reply", true); $this->setCache('has_reply', true);
$operation["reply"] = $msg; $operation['reply'] = $msg;
$operation["at_sender"] = false; $operation['at_sender'] = false;
return (new ZMRobot($conn))->setCallback($yield)->callExtendedAPI(".handle_quick_operation", [ return (new ZMRobot($conn))->setCallback($yield)->callExtendedAPI('.handle_quick_operation', [
"context" => $data, 'context' => $data,
"operation" => $operation 'operation' => $operation,
]); ]);
} }
return false; return false;
} else {
$operation = $msg;
return (new ZMRobot($conn))->setCallback(false)->callExtendedAPI(".handle_quick_operation", [
"context" => $data,
"operation" => $operation
]);
} }
$operation = $msg;
return (new ZMRobot($conn))->setCallback(false)->callExtendedAPI('.handle_quick_operation', [
'context' => $data,
'operation' => $operation,
]);
} }
/** /**
* @param $msg * @param $msg
* @param false $yield * @param bool $yield
* @return void
* @throws InterruptException * @throws InterruptException
*/ */
public function finalReply($msg, $yield = false) { public function finalReply($msg, $yield = false)
self::$context[$this->cid]["cache"]["block_continue"] = true; {
if ($msg != "") $this->reply($msg, $yield); self::$context[$this->cid]['cache']['block_continue'] = true;
if ($msg != '') {
$this->reply($msg, $yield);
}
EventDispatcher::interrupt(); EventDispatcher::interrupt();
} }
/** /**
* @param string $prompt * @param string $prompt
* @param int $timeout * @param int $timeout
* @param string $timeout_prompt * @param string $timeout_prompt
* @return string
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws WaitTimeoutException * @throws WaitTimeoutException
* @return string
* @noinspection PhpMissingReturnTypeInspection * @noinspection PhpMissingReturnTypeInspection
*/ */
public function waitMessage($prompt = "", $timeout = 600, $timeout_prompt = "") { public function waitMessage($prompt = '', $timeout = 600, $timeout_prompt = '')
if (!isset($this->getData()["user_id"], $this->getData()["message"], $this->getData()["self_id"])) {
throw new InvalidArgumentException("协程等待参数缺失"); if (!isset($this->getData()['user_id'], $this->getData()['message'], $this->getData()['self_id'])) {
throw new InvalidArgumentException('协程等待参数缺失');
}
Console::debug("==== 开始等待输入 ===="); Console::debug('==== 开始等待输入 ====');
if ($prompt != "") $this->reply($prompt); if ($prompt != '') {
$this->reply($prompt);
}
try { try {
$r = CoMessage::yieldByWS($this->getData(), ["user_id", "self_id", "message_type", onebot_target_id_name($this->getMessageType())], $timeout); $r = CoMessage::yieldByWS($this->getData(), ['user_id', 'self_id', 'message_type', onebot_target_id_name($this->getMessageType())], $timeout);
} catch (Exception $e) { } catch (Exception $e) {
$r = false; $r = false;
} }
if ($r === false) { if ($r === false) {
throw new WaitTimeoutException($this, $timeout_prompt); throw new WaitTimeoutException($this, $timeout_prompt);
} }
if (is_array($r["message"]) && (ZMConfig::get("global", "onebot")["message_convert_string"] ?? true) === true) { if (is_array($r['message']) && (ZMConfig::get('global', 'onebot')['message_convert_string'] ?? true) === true) {
return MessageUtil::arrayToStr($r["message"]); return MessageUtil::arrayToStr($r['message']);
} else {
return $r["message"];
} }
return $r['message'];
} }
/** /**
* @param $mode * @param $mode
* @param $prompt_msg * @param $prompt_msg
* @return mixed|string
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws WaitTimeoutException * @throws WaitTimeoutException
* @return mixed|string
*/ */
public function getArgs($mode, $prompt_msg) { public function getArgs($mode, $prompt_msg)
$arg = ctx()->getCache("match") ?? []; {
$arg = ctx()->getCache('match') ?? [];
switch ($mode) { switch ($mode) {
case ZM_MATCH_ALL: case ZM_MATCH_ALL:
$p = $arg; $p = $arg;
return trim(implode(" ", $p)) == "" ? $this->waitMessage($prompt_msg) : trim(implode(" ", $p)); return trim(implode(' ', $p)) == '' ? $this->waitMessage($prompt_msg) : trim(implode(' ', $p));
case ZM_MATCH_NUMBER: case ZM_MATCH_NUMBER:
foreach ($arg as $k => $v) { foreach ($arg as $k => $v) {
if (is_numeric($v)) { if (is_numeric($v)) {
array_splice($arg, $k, 1); array_splice($arg, $k, 1);
ctx()->setCache("match", $arg); ctx()->setCache('match', $arg);
return $v; return $v;
} }
} }
@@ -214,60 +273,84 @@ class Context implements ContextInterface
if (isset($arg[0])) { if (isset($arg[0])) {
$a = $arg[0]; $a = $arg[0];
array_splice($arg, 0, 1); array_splice($arg, 0, 1);
ctx()->setCache("match", $arg); ctx()->setCache('match', $arg);
return $a; return $a;
} else {
return $this->waitMessage($prompt_msg);
} }
return $this->waitMessage($prompt_msg);
} }
throw new InvalidArgumentException(); throw new InvalidArgumentException();
} }
/** /**
* @param string $prompt_msg * @param string $prompt_msg
* @return int|mixed|string
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws WaitTimeoutException * @throws WaitTimeoutException
* @return int|mixed|string
*/ */
public function getNextArg($prompt_msg = "") { return $this->getArgs(ZM_MATCH_FIRST, $prompt_msg); } public function getNextArg($prompt_msg = '')
{
return $this->getArgs(ZM_MATCH_FIRST, $prompt_msg);
}
/** /**
* @param string $prompt_msg * @param string $prompt_msg
* @return int|mixed|string
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws WaitTimeoutException * @throws WaitTimeoutException
* @return int|mixed|string
*/ */
public function getFullArg($prompt_msg = "") { return $this->getArgs(ZM_MATCH_ALL, $prompt_msg); } public function getFullArg($prompt_msg = '')
{
return $this->getArgs(ZM_MATCH_ALL, $prompt_msg);
}
/** /**
* @param string $prompt_msg * @param string $prompt_msg
* @return int|mixed|string
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws WaitTimeoutException * @throws WaitTimeoutException
* @return int|mixed|string
*/ */
public function getNumArg($prompt_msg = "") { return $this->getArgs(ZM_MATCH_NUMBER, $prompt_msg); } public function getNumArg($prompt_msg = '')
{
return $this->getArgs(ZM_MATCH_NUMBER, $prompt_msg);
}
/** @noinspection PhpMissingReturnTypeInspection */ /** @noinspection PhpMissingReturnTypeInspection */
public function cloneFromParent() { public function cloneFromParent()
{
set_coroutine_params(self::$context[Coroutine::getPcid()] ?? self::$context[$this->cid]); set_coroutine_params(self::$context[Coroutine::getPcid()] ?? self::$context[$this->cid]);
return context(); return context();
} }
public function copy() { return self::$context[$this->cid]; } public function copy()
{
public function getOption() { return self::getCache("match"); } return self::$context[$this->cid];
public function getOriginMessage() { return self::$context[$this->cid]["data"]["message"] ?? null; }
public function getArrayMessage(): array {
$msg = $this->getOriginMessage();
if (is_array($msg)) return $msg;
else return MessageUtil::strToArray($msg);
} }
public function getStringMessage(): string { public function getOption()
{
return self::getCache('match');
}
public function getOriginMessage()
{
return self::$context[$this->cid]['data']['message'] ?? null;
}
public function getArrayMessage(): array
{
$msg = $this->getOriginMessage(); $msg = $this->getOriginMessage();
if (is_string($msg)) return $msg; if (is_array($msg)) {
else return MessageUtil::arrayToStr($msg); return $msg;
}
return MessageUtil::strToArray($msg);
}
public function getStringMessage(): string
{
$msg = $this->getOriginMessage();
if (is_string($msg)) {
return $msg;
}
return MessageUtil::arrayToStr($msg);
} }
} }

View File

@@ -1,15 +1,15 @@
<?php /** @noinspection PhpMissingReturnTypeInspection */ <?php
declare(strict_types=1);
namespace ZM\Context; namespace ZM\Context;
use Swoole\Http\Request; use Swoole\Http\Request;
use Swoole\WebSocket\Frame; use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server; use Swoole\WebSocket\Server;
use ZM\API\ZMRobot;
use ZM\ConnectionManager\ConnectionObject; use ZM\ConnectionManager\ConnectionObject;
use ZM\Http\Response; use ZM\Http\Response;
use ZM\API\ZMRobot;
interface ContextInterface interface ContextInterface
{ {
@@ -29,7 +29,7 @@ interface ContextInterface
/** @return ConnectionObject */ /** @return ConnectionObject */
public function getConnection(); public function getConnection();
/** @return int|null */ /** @return null|int */
public function getFd(); public function getFd();
/** @return int */ /** @return int */
@@ -74,50 +74,25 @@ interface ContextInterface
public function getCQResponse(); public function getCQResponse();
/**
* @param $msg
* @param bool $yield
* @return mixed
*/
public function reply($msg, $yield = false); public function reply($msg, $yield = false);
/**
* @param $msg
* @param bool $yield
* @return mixed
*/
public function finalReply($msg, $yield = false); public function finalReply($msg, $yield = false);
/** public function waitMessage($prompt = '', $timeout = 600, $timeout_prompt = '');
* @param string $prompt
* @param int $timeout
* @param string $timeout_prompt
* @return mixed
*/
public function waitMessage($prompt = "", $timeout = 600, $timeout_prompt = "");
/**
* @param $mode
* @param $prompt_msg
* @return mixed
*/
public function getArgs($mode, $prompt_msg); public function getArgs($mode, $prompt_msg);
public function getNextArg($prompt_msg = ""); public function getNextArg($prompt_msg = '');
public function getFullArg($prompt_msg = ""); public function getFullArg($prompt_msg = '');
public function setCache($key, $value); public function setCache($key, $value);
/**
* @param $key
* @return mixed
*/
public function getCache($key); public function getCache($key);
public function cloneFromParent(); public function cloneFromParent();
public function getNumArg($prompt_msg = ""); public function getNumArg($prompt_msg = '');
public function copy(); public function copy();

View File

@@ -1,22 +1,23 @@
<?php /** @noinspection PhpUnused */ <?php
/** @noinspection PhpComposerExtensionStubsInspection */ /** @noinspection PhpComposerExtensionStubsInspection */
declare(strict_types=1);
/** @noinspection PhpUnused */
namespace ZM\DB; namespace ZM\DB;
use ZM\Console\Console;
use ZM\MySQL\MySQLManager;
use ZM\Store\MySQL\SqlPoolStorage;
use PDOException; use PDOException;
use PDOStatement; use PDOStatement;
use Swoole\Database\PDOStatementProxy; use Swoole\Database\PDOStatementProxy;
use ZM\Console\Console;
use ZM\Exception\DbException; use ZM\Exception\DbException;
use ZM\MySQL\MySQLManager;
use ZM\Store\MySQL\SqlPoolStorage;
/** /**
* Class DB * Class DB
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
class DB class DB
@@ -27,9 +28,12 @@ class DB
* @param $db_name * @param $db_name
* @throws DbException * @throws DbException
*/ */
public static function initTableList($db_name) { public static function initTableList($db_name)
if (!extension_loaded("mysqlnd")) throw new DbException("Can not find mysqlnd PHP extension."); {
$result = MySQLManager::getWrapper()->fetchAllAssociative("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=?;", [$db_name]); if (!extension_loaded('mysqlnd')) {
throw new DbException('Can not find mysqlnd PHP extension.');
}
$result = MySQLManager::getWrapper()->fetchAllAssociative('select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA=?;', [$db_name]);
foreach ($result as $v) { foreach ($result as $v) {
self::$table_list[] = $v['TABLE_NAME']; self::$table_list[] = $v['TABLE_NAME'];
} }
@@ -37,18 +41,18 @@ class DB
/** /**
* @param $table_name * @param $table_name
* @return Table
* @throws DbException * @throws DbException
*/ */
public static function table($table_name): Table { public static function table($table_name): Table
{
if (Table::getTableInstance($table_name) === null) { if (Table::getTableInstance($table_name) === null) {
if (in_array($table_name, self::$table_list)) if (in_array($table_name, self::$table_list)) {
return new Table($table_name); return new Table($table_name);
elseif (SqlPoolStorage::$sql_pool !== null) {
throw new DbException("Table " . $table_name . " not exist in database.");
} else {
throw new DbException("Database connection not exist or connect failed. Please check sql configuration");
} }
if (SqlPoolStorage::$sql_pool !== null) {
throw new DbException('Table ' . $table_name . ' not exist in database.');
}
throw new DbException('Database connection not exist or connect failed. Please check sql configuration');
} }
return Table::getTableInstance($table_name); return Table::getTableInstance($table_name);
} }
@@ -57,23 +61,24 @@ class DB
* @param $line * @param $line
* @throws DbException * @throws DbException
*/ */
public static function statement($line) { public static function statement($line)
{
self::rawQuery($line, []); self::rawQuery($line, []);
} }
/** /**
* @param $line * @param $line
* @return bool
* @throws DbException * @throws DbException
*/ */
public static function unprepared($line): bool { public static function unprepared($line): bool
{
try { try {
$conn = SqlPoolStorage::$sql_pool->getConnection(); $conn = SqlPoolStorage::$sql_pool->getConnection();
if ($conn === false) { if ($conn === false) {
SqlPoolStorage::$sql_pool->putConnection(null); SqlPoolStorage::$sql_pool->putConnection(null);
throw new DbException("无法连接SQL" . $line); throw new DbException('无法连接SQL' . $line);
} }
$result = $conn->query($line) === false ? false : true; $result = !($conn->query($line) === false);
SqlPoolStorage::$sql_pool->putConnection($conn); SqlPoolStorage::$sql_pool->putConnection($conn);
return $result; return $result;
} catch (DBException $e) { } catch (DBException $e) {
@@ -82,58 +87,58 @@ class DB
} }
} }
/** public static function rawQuery(string $line, $params = [], $fetch_mode = ZM_DEFAULT_FETCH_MODE)
* @param string $line {
* @param array $params if (!is_array($params)) {
* @param int $fetch_mode $params = [$params];
* @return mixed }
* @throws DbException Console::debug('MySQL: ' . $line . ' | ' . implode(', ', $params));
*/
public static function rawQuery(string $line, $params = [], $fetch_mode = ZM_DEFAULT_FETCH_MODE) {
if (!is_array($params)) $params = [$params];
Console::debug("MySQL: " . $line . " | " . implode(", ", $params));
try { try {
if (SqlPoolStorage::$sql_pool === null) throw new DbException("未连接到任何数据库!"); if (SqlPoolStorage::$sql_pool === null) {
throw new DbException('未连接到任何数据库!');
}
$conn = SqlPoolStorage::$sql_pool->getConnection(); $conn = SqlPoolStorage::$sql_pool->getConnection();
if ($conn === false) { if ($conn === false) {
SqlPoolStorage::$sql_pool->putConnection(null); SqlPoolStorage::$sql_pool->putConnection(null);
throw new DbException("无法连接SQL" . $line); throw new DbException('无法连接SQL' . $line);
} }
$ps = $conn->prepare($line); $ps = $conn->prepare($line);
if ($ps === false) { if ($ps === false) {
SqlPoolStorage::$sql_pool->putConnection(null); SqlPoolStorage::$sql_pool->putConnection(null);
/** @noinspection PhpUndefinedFieldInspection */ /* @noinspection PhpUndefinedFieldInspection */
throw new DbException("SQL语句查询错误" . $line . ",错误信息:" . $conn->error); throw new DbException('SQL语句查询错误' . $line . ',错误信息:' . $conn->error);
} else {
if (!($ps instanceof PDOStatement) && !($ps instanceof PDOStatementProxy)) {
var_dump($ps);
SqlPoolStorage::$sql_pool->putConnection(null);
throw new DbException("语句查询错误!返回的不是 PDOStatement" . $line);
}
if ($params == []) $result = $ps->execute();
elseif (!is_array($params)) {
$result = $ps->execute([$params]);
} else $result = $ps->execute($params);
if ($result !== true) {
SqlPoolStorage::$sql_pool->putConnection(null);
throw new DBException("语句[$line]错误!" . $ps->errorInfo()[2]);
//echo json_encode(debug_backtrace(), 128 | 256);
}
SqlPoolStorage::$sql_pool->putConnection($conn);
return $ps->fetchAll($fetch_mode);
} }
if (!($ps instanceof PDOStatement) && !($ps instanceof PDOStatementProxy)) {
var_dump($ps);
SqlPoolStorage::$sql_pool->putConnection(null);
throw new DbException('语句查询错误!返回的不是 PDOStatement' . $line);
}
if ($params == []) {
$result = $ps->execute();
} elseif (!is_array($params)) {
$result = $ps->execute([$params]);
} else {
$result = $ps->execute($params);
}
if ($result !== true) {
SqlPoolStorage::$sql_pool->putConnection(null);
throw new DBException("语句[{$line}]错误!" . $ps->errorInfo()[2]);
//echo json_encode(debug_backtrace(), 128 | 256);
}
SqlPoolStorage::$sql_pool->putConnection($conn);
return $ps->fetchAll($fetch_mode);
} catch (DbException $e) { } catch (DbException $e) {
if (mb_strpos($e->getMessage(), "has gone away") !== false) { if (mb_strpos($e->getMessage(), 'has gone away') !== false) {
zm_sleep(0.2); zm_sleep(0.2);
Console::warning("Gone away of MySQL! retrying!"); Console::warning('Gone away of MySQL! retrying!');
return self::rawQuery($line, $params); return self::rawQuery($line, $params);
} }
Console::warning($e->getMessage()); Console::warning($e->getMessage());
throw $e; throw $e;
} catch (PDOException $e) { } catch (PDOException $e) {
if (mb_strpos($e->getMessage(), "has gone away") !== false) { if (mb_strpos($e->getMessage(), 'has gone away') !== false) {
zm_sleep(0.2); zm_sleep(0.2);
Console::warning("Gone away of MySQL! retrying!"); Console::warning('Gone away of MySQL! retrying!');
return self::rawQuery($line, $params); return self::rawQuery($line, $params);
} }
Console::warning($e->getMessage()); Console::warning($e->getMessage());
@@ -141,7 +146,8 @@ class DB
} }
} }
public static function isTableExists($table): bool { public static function isTableExists($table): bool
{
return in_array($table, self::$table_list); return in_array($table, self::$table_list);
} }
} }

View File

@@ -1,14 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace ZM\DB; namespace ZM\DB;
use ZM\Exception\DbException; use ZM\Exception\DbException;
/** /**
* Class DeleteBody * Class DeleteBody
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
class DeleteBody class DeleteBody
@@ -22,18 +21,19 @@ class DeleteBody
/** /**
* DeleteBody constructor. * DeleteBody constructor.
* @param Table $table
*/ */
public function __construct(Table $table) { public function __construct(Table $table)
{
$this->table = $table; $this->table = $table;
} }
/** /**
* @return mixed
* @throws DbException * @throws DbException
* @return mixed
*/ */
public function save() { public function save()
list($sql, $param) = $this->getWhereSQL(); {
return DB::rawQuery("DELETE FROM " . $this->table->getTableName() . " WHERE " . $sql, $param); [$sql, $param] = $this->getWhereSQL();
return DB::rawQuery('DELETE FROM ' . $this->table->getTableName() . ' WHERE ' . $sql, $param);
} }
} }

View File

@@ -1,14 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace ZM\DB; namespace ZM\DB;
use ZM\Exception\DbException; use ZM\Exception\DbException;
/** /**
* Class InsertBody * Class InsertBody
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
class InsertBody class InsertBody
@@ -17,14 +16,15 @@ class InsertBody
* @var Table * @var Table
*/ */
private $table; private $table;
private $row; private $row;
/** /**
* InsertBody constructor. * InsertBody constructor.
* @param Table $table
* @param $row * @param $row
*/ */
public function __construct(Table $table, $row) { public function __construct(Table $table, $row)
{
$this->table = $table; $this->table = $table;
$this->row = $row; $this->row = $row;
} }
@@ -32,7 +32,8 @@ class InsertBody
/** /**
* @throws DbException * @throws DbException
*/ */
public function save() { public function save()
{
DB::rawQuery('INSERT INTO ' . $this->table->getTableName() . ' VALUES (' . implode(',', array_fill(0, count($this->row), '?')) . ')', $this->row); DB::rawQuery('INSERT INTO ' . $this->table->getTableName() . ' VALUES (' . implode(',', array_fill(0, count($this->row), '?')) . ')', $this->row);
} }
} }

View File

@@ -1,14 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace ZM\DB; namespace ZM\DB;
use ZM\Exception\DbException; use ZM\Exception\DbException;
/** /**
* Class SelectBody * Class SelectBody
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
class SelectBody class SelectBody
@@ -20,96 +19,119 @@ class SelectBody
private $select_thing; private $select_thing;
private $result;
private $result = null; public function __construct($table, $select_thing)
{
public function __construct($table, $select_thing) {
$this->table = $table; $this->table = $table;
$this->select_thing = $select_thing; $this->select_thing = $select_thing;
} }
/** /**
* @return null
* @throws DbException * @throws DbException
*/ */
public function get() { return $this->fetchAll(); } public function get()
{
/** return $this->fetchAll();
* @throws DbException
*/
public function count(): int {
$this->select_thing = ["count(*)"];
$str = $this->queryPrepare();
$this->result = DB::rawQuery($str[0], $str[1]);
return intval($this->result[0]["count(*)"]);
} }
/** /**
* @param int $fetch_mode
* @return null
* @throws DbException * @throws DbException
*/ */
public function fetchAll($fetch_mode = ZM_DEFAULT_FETCH_MODE) { public function count(): int
{
$this->select_thing = ['count(*)'];
$str = $this->queryPrepare();
$this->result = DB::rawQuery($str[0], $str[1]);
return intval($this->result[0]['count(*)']);
}
/**
* @param int $fetch_mode
* @throws DbException
*/
public function fetchAll($fetch_mode = ZM_DEFAULT_FETCH_MODE)
{
$this->execute($fetch_mode); $this->execute($fetch_mode);
return $this->getResult(); return $this->getResult();
} }
/** /**
* @return mixed|null
* @throws DbException * @throws DbException
* @return null|mixed
*/ */
public function fetchFirst() { public function fetchFirst()
{
return $this->fetchAll()[0] ?? null; return $this->fetchAll()[0] ?? null;
} }
/** /**
* @param null $key * @param null $key
* @return mixed|null
* @throws DbException * @throws DbException
* @return null|mixed
*/ */
public function value($key = null) { public function value($key = null)
{
$r = $this->fetchFirst(); $r = $this->fetchFirst();
if ($r === null) return null; if ($r === null) {
if ($key === null) return null;
}
if ($key === null) {
return current($r); return current($r);
else return $r[$key] ?? null; }
return $r[$key] ?? null;
} }
/** /**
* @param int $fetch_mode * @param int $fetch_mode
* @throws DbException * @throws DbException
*/ */
public function execute($fetch_mode = ZM_DEFAULT_FETCH_MODE) { public function execute($fetch_mode = ZM_DEFAULT_FETCH_MODE)
{
$str = $this->queryPrepare(); $str = $this->queryPrepare();
$this->result = DB::rawQuery($str[0], $str[1], $fetch_mode); $this->result = DB::rawQuery($str[0], $str[1], $fetch_mode);
} }
public function getResult() { return $this->result; } public function getResult()
{
return $this->result;
}
public function equals(SelectBody $body): bool { public function equals(SelectBody $body): bool
if ($this->select_thing != $body->getSelectThing()) return false; {
elseif ($this->where_thing == $body->getWhereThing()) return false; if ($this->select_thing != $body->getSelectThing()) {
else return true; return false;
}
if ($this->where_thing == $body->getWhereThing()) {
return false;
}
return true;
} }
/** /**
* @return mixed * @return mixed
*/ */
public function getSelectThing() { return $this->select_thing; } public function getSelectThing()
{
return $this->select_thing;
}
/** public function getWhereThing(): array
* @return array {
*/ return $this->where_thing;
public function getWhereThing(): array { return $this->where_thing; } }
private function queryPrepare(): array { private function queryPrepare(): array
$msg = "SELECT " . implode(", ", $this->select_thing) . " FROM " . $this->table->getTableName(); {
$msg = 'SELECT ' . implode(', ', $this->select_thing) . ' FROM ' . $this->table->getTableName();
$sql = $this->table->paintWhereSQL($this->where_thing['='] ?? [], '='); $sql = $this->table->paintWhereSQL($this->where_thing['='] ?? [], '=');
if ($sql[0] != '') { if ($sql[0] != '') {
$msg .= " WHERE " . $sql[0]; $msg .= ' WHERE ' . $sql[0];
$array = $sql[1]; $array = $sql[1];
$sql = $this->table->paintWhereSQL($this->where_thing['!='] ?? [], '!='); $sql = $this->table->paintWhereSQL($this->where_thing['!='] ?? [], '!=');
if ($sql[0] != '') $msg .= " AND " . $sql[0]; if ($sql[0] != '') {
$msg .= ' AND ' . $sql[0];
}
$array = array_merge($array, $sql[1]); $array = array_merge($array, $sql[1]);
} }
return [$msg, $array ?? []]; return [$msg, $array ?? []];

View File

@@ -1,71 +1,87 @@
<?php /** @noinspection PhpUnused */ <?php
/** @noinspection PhpMissingReturnTypeInspection */ /**
* @noinspection PhpMissingReturnTypeInspection
* @noinspection PhpUnused
*/
declare(strict_types=1);
namespace ZM\DB; namespace ZM\DB;
/** /**
* Class Table * Class Table
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
class Table class Table
{ {
private $table_name;
/** @var SelectBody[] */ /** @var SelectBody[] */
public $cache = []; public $cache = [];
private $table_name;
private static $table_instance = []; private static $table_instance = [];
public function __construct($table_name) { public function __construct($table_name)
{
$this->table_name = $table_name; $this->table_name = $table_name;
self::$table_instance[$table_name] = $this; self::$table_instance[$table_name] = $this;
} }
public static function getTableInstance($table_name) { public static function getTableInstance($table_name)
if (isset(self::$table_instance[$table_name])) return self::$table_instance[$table_name]; {
else return null; if (isset(self::$table_instance[$table_name])) {
return self::$table_instance[$table_name];
}
return null;
} }
public function select($what = []) { public function select($what = [])
return new SelectBody($this, $what == [] ? ["*"] : $what); {
return new SelectBody($this, $what == [] ? ['*'] : $what);
} }
public function where($column, $operation_or_value, $value = null) { public function where($column, $operation_or_value, $value = null)
return (new SelectBody($this, ["*"]))->where($column, $operation_or_value, $value); {
return (new SelectBody($this, ['*']))->where($column, $operation_or_value, $value);
} }
public function insert($row) { public function insert($row)
{
$this->cache = []; $this->cache = [];
return new InsertBody($this, $row); return new InsertBody($this, $row);
} }
public function update(array $set_value) { public function update(array $set_value)
{
$this->cache = []; $this->cache = [];
return new UpdateBody($this, $set_value); return new UpdateBody($this, $set_value);
} }
public function delete() { public function delete()
{
$this->cache = []; $this->cache = [];
return new DeleteBody($this); return new DeleteBody($this);
} }
public function statement() { public function statement()
{
$this->cache = []; $this->cache = [];
//TODO: 无返回的statement语句 //TODO: 无返回的statement语句
} }
public function paintWhereSQL($rule, $operator) { public function paintWhereSQL($rule, $operator)
if ($rule == []) return ["", []]; {
$msg = ""; if ($rule == []) {
return ['', []];
}
$msg = '';
$param = []; $param = [];
foreach ($rule as $k => $v) { foreach ($rule as $k => $v) {
if ($msg == "") { if ($msg == '') {
$msg .= $k . " $operator ? "; $msg .= $k . " {$operator} ? ";
} else { } else {
$msg .= " AND " . $k . " $operator ?"; $msg .= ' AND ' . $k . " {$operator} ?";
} }
$param[] = $v; $param[] = $v;
} }
@@ -75,6 +91,8 @@ class Table
/** /**
* @return mixed * @return mixed
*/ */
public function getTableName() { return $this->table_name; } public function getTableName()
{
return $this->table_name;
}
} }

View File

@@ -1,14 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace ZM\DB; namespace ZM\DB;
use ZM\Exception\DbException; use ZM\Exception\DbException;
/** /**
* Class UpdateBody * Class UpdateBody
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
class UpdateBody class UpdateBody
@@ -19,6 +18,7 @@ class UpdateBody
* @var Table * @var Table
*/ */
private $table; private $table;
/** /**
* @var array * @var array
*/ */
@@ -26,10 +26,9 @@ class UpdateBody
/** /**
* UpdateBody constructor. * UpdateBody constructor.
* @param Table $table
* @param array $set_value
*/ */
public function __construct(Table $table, array $set_value) { public function __construct(Table $table, array $set_value)
{
$this->table = $table; $this->table = $table;
$this->set_value = $set_value; $this->set_value = $set_value;
} }
@@ -37,17 +36,20 @@ class UpdateBody
/** /**
* @throws DbException * @throws DbException
*/ */
public function save() { public function save()
{
$arr = []; $arr = [];
$msg = []; $msg = [];
foreach ($this->set_value as $k => $v) { foreach ($this->set_value as $k => $v) {
$msg [] = $k . ' = ?'; $msg[] = $k . ' = ?';
$arr[] = $v; $arr[] = $v;
} }
if (($msg ?? []) == []) throw new DbException('update value sets can not be empty!'); if (($msg ?? []) == []) {
throw new DbException('update value sets can not be empty!');
}
$line = 'UPDATE ' . $this->table->getTableName() . ' SET ' . implode(', ', $msg); $line = 'UPDATE ' . $this->table->getTableName() . ' SET ' . implode(', ', $msg);
if ($this->where_thing != []) { if ($this->where_thing != []) {
list($sql, $param) = $this->getWhereSQL(); [$sql, $param] = $this->getWhereSQL();
$arr = array_merge($arr, $param); $arr = array_merge($arr, $param);
$line .= ' WHERE ' . $sql; $line .= ' WHERE ' . $sql;
} }

View File

@@ -1,38 +1,48 @@
<?php /** @noinspection PhpMissingReturnTypeInspection */ <?php
/** @noinspection PhpMissingReturnTypeInspection */
declare(strict_types=1);
namespace ZM\DB; namespace ZM\DB;
/** /**
* Trait WhereBody * Trait WhereBody
* @package ZM\DB
* @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead * @deprecated This will delete in 2.6 or future version, use \ZM\MySQL\MySQLManager::getConnection() instead
*/ */
trait WhereBody trait WhereBody
{ {
protected $where_thing = []; protected $where_thing = [];
public function where($column, $operation_or_value, $value = null) { public function where($column, $operation_or_value, $value = null)
if ($value !== null) $this->where_thing[$operation_or_value][$column] = $value; {
elseif (!in_array($operation_or_value, ['=', '!=', '>', '<', '>=', '<=', 'IN', 'in'])) $this->where_thing['='][$column] = $operation_or_value; if ($value !== null) {
else $this->where_thing['='][$column] = $operation_or_value; $this->where_thing[$operation_or_value][$column] = $value;
} elseif (!in_array($operation_or_value, ['=', '!=', '>', '<', '>=', '<=', 'IN', 'in'])) {
$this->where_thing['='][$column] = $operation_or_value;
} else {
$this->where_thing['='][$column] = $operation_or_value;
}
return $this; return $this;
} }
protected function getWhereSQL() { protected function getWhereSQL()
{
$param = []; $param = [];
$msg = ''; $msg = '';
foreach ($this->where_thing as $k => $v) { foreach ($this->where_thing as $k => $v) {
foreach ($v as $ks => $vs) { foreach ($v as $ks => $vs) {
if ($param != []) { if ($param != []) {
$msg .= ' AND ' . $ks . " $k ?"; $msg .= ' AND ' . $ks . " {$k} ?";
} else { } else {
$msg .= "$ks $k ?"; $msg .= "{$ks} {$k} ?";
} }
$param [] = $vs; $param[] = $vs;
} }
} }
if ($msg == '') $msg = 1; if ($msg == '') {
$msg = 1;
}
return [$msg, $param]; return [$msg, $param];
} }
} }

View File

@@ -1,18 +1,22 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Entity; namespace ZM\Entity;
class CQObject class CQObject
{ {
public $type; public $type;
public $params; public $params;
public $start; public $start;
public $end; public $end;
public function __construct($type = "", $params = [], $start = 0, $end = 0) { public function __construct($type = '', $params = [], $start = 0, $end = 0)
if ($type !== "") { {
if ($type !== '') {
$this->type = $type; $this->type = $type;
$this->params = $params; $this->params = $params;
$this->start = $start; $this->start = $start;
@@ -20,7 +24,8 @@ class CQObject
} }
} }
public static function fromArray($arr): CQObject { public static function fromArray($arr): CQObject
return new CQObject($arr["type"], $arr["params"] ?? [], $arr["start"], $arr["end"]); {
return new CQObject($arr['type'], $arr['params'] ?? [], $arr['start'], $arr['end']);
} }
} }

View File

@@ -1,17 +1,19 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Entity; namespace ZM\Entity;
use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\CQ\CQCommand;
class MatchResult class MatchResult
{ {
/** @var bool */ /** @var bool */
public $status = false; public $status = false;
/** @var CQCommand|null */
public $object = null; /** @var null|CQCommand */
public $object;
/** @var array */ /** @var array */
public $match = []; public $match = [];
} }

View File

@@ -1,9 +1,10 @@
<?php /** @noinspection PhpUnused */ <?php
declare(strict_types=1);
/** @noinspection PhpUnused */
namespace ZM\Event; namespace ZM\Event;
use Closure; use Closure;
use Doctrine\Common\Annotations\AnnotationException; use Doctrine\Common\Annotations\AnnotationException;
use Error; use Error;
@@ -18,113 +19,151 @@ use ZM\Utils\ZMUtil;
class EventDispatcher class EventDispatcher
{ {
const STATUS_NORMAL = 0; //正常结束 public const STATUS_NORMAL = 0; //正常结束
const STATUS_INTERRUPTED = 1; //被interrupt了不管在什么地方
const STATUS_EXCEPTION = 2; //执行过程中抛出了异常 public const STATUS_INTERRUPTED = 1; //被interrupt了不管在什么地方
const STATUS_BEFORE_FAILED = 3; //中间件HandleBefore返回了false所以不执行此方法
const STATUS_RULE_FAILED = 4; //判断事件执行的规则函数判定为false所以不执行此方法 public const STATUS_EXCEPTION = 2; //执行过程中抛出了异常
public const STATUS_BEFORE_FAILED = 3; //中间件HandleBefore返回了false所以不执行此方法
public const STATUS_RULE_FAILED = 4; //判断事件执行的规则函数判定为false所以不执行此方法
/** @var int */
public $status = self::STATUS_NORMAL;
/** @var mixed */
public $store;
/** @var string */ /** @var string */
private $class; private $class;
/** @var null|callable */ /** @var null|callable */
private $rule = null; private $rule;
/** @var null|callable */ /** @var null|callable */
private $return_func = null; private $return_func;
/** @var bool */ /** @var bool */
private $log = false; private $log = false;
/** @var int */ /** @var int */
private $eid; private $eid;
/** @var int */
public $status = self::STATUS_NORMAL; public function __construct(string $class = '')
/** @var mixed */ {
public $store = null; $this->class = $class;
$this->eid = ZMAtomic::get('_event_id')->add(1);
$list = LightCacheInside::get('wait_api', 'event_trace');
if (isset($list[$class])) {
$this->log = true;
}
if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 开始分发事件: " . $class);
}
}
/** /**
* @param null $return_var * @param mixed $return_var
* @throws InterruptException * @throws InterruptException
*/ */
public static function interrupt($return_var = null) { public static function interrupt($return_var = null)
{
throw new InterruptException($return_var); throw new InterruptException($return_var);
} }
public static function enableEventTrace($event_class) { public static function enableEventTrace($event_class)
SpinLock::lock("_event_trace"); {
$list = LightCacheInside::get("wait_api", "event_trace"); SpinLock::lock('_event_trace');
$list = LightCacheInside::get('wait_api', 'event_trace');
$list[$event_class] = true; $list[$event_class] = true;
LightCacheInside::set("wait_api", "event_trace", $list); LightCacheInside::set('wait_api', 'event_trace', $list);
SpinLock::unlock("_event_trace"); SpinLock::unlock('_event_trace');
} }
public static function disableEventTrace($event_class) { public static function disableEventTrace($event_class)
SpinLock::lock("_event_trace"); {
$list = LightCacheInside::get("wait_api", "event_trace"); SpinLock::lock('_event_trace');
$list = LightCacheInside::get('wait_api', 'event_trace');
unset($list[$event_class]); unset($list[$event_class]);
LightCacheInside::set("wait_api", "event_trace", $list); LightCacheInside::set('wait_api', 'event_trace', $list);
SpinLock::unlock("_event_trace"); SpinLock::unlock('_event_trace');
} }
public function __construct(string $class = '') { public function setRuleFunction(callable $rule = null): EventDispatcher
$this->class = $class; {
$this->eid = ZMAtomic::get("_event_id")->add(1); if ($this->log) {
$list = LightCacheInside::get("wait_api", "event_trace"); Console::verbose("[事件分发{$this->eid}] 设置事件rule: " . $this->class);
if (isset($list[$class])) $this->log = true; }
if ($this->log) Console::verbose("[事件分发{$this->eid}] 开始分发事件: " . $class);
}
public function setRuleFunction(callable $rule = null): EventDispatcher {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 设置事件rule: " . $this->class);
$this->rule = $rule; $this->rule = $rule;
return $this; return $this;
} }
public function setReturnFunction(callable $return_func): EventDispatcher { public function setReturnFunction(callable $return_func): EventDispatcher
if ($this->log) Console::verbose("[事件分发{$this->eid}] 设置事件returnFunc: " . $this->class); {
if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 设置事件returnFunc: " . $this->class);
}
$this->return_func = $return_func; $this->return_func = $return_func;
return $this; return $this;
} }
/** /**
* @param mixed ...$params * @param mixed ...$params
* @throws Exception * @throws Exception
*/ */
public function dispatchEvents(...$params) { public function dispatchEvents(...$params)
{
try { try {
foreach ((EventManager::$events[$this->class] ?? []) as $v) { foreach ((EventManager::$events[$this->class] ?? []) as $v) {
$this->dispatchEvent($v, $this->rule, ...$params); $this->dispatchEvent($v, $this->rule, ...$params);
if ($this->log) Console::verbose("[事件分发{$this->eid}] 单一对象 " . $v->class . "::" . (is_string($v->method) ? $v->method : "{closure}") . " 分发结束。"); if ($this->log) {
if ($this->status == self::STATUS_BEFORE_FAILED || $this->status == self::STATUS_RULE_FAILED) continue; Console::verbose("[事件分发{$this->eid}] 单一对象 " . $v->class . '::' . (is_string($v->method) ? $v->method : '{closure}') . ' 分发结束。');
}
if ($this->status == self::STATUS_BEFORE_FAILED || $this->status == self::STATUS_RULE_FAILED) {
continue;
}
if (is_callable($this->return_func) && $this->status === self::STATUS_NORMAL) { if (is_callable($this->return_func) && $this->status === self::STATUS_NORMAL) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 单一对象 " . $v->class . "::" . $v->method . " 正在执行返回值处理函数 ..."); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 单一对象 " . $v->class . '::' . $v->method . ' 正在执行返回值处理函数 ...');
}
($this->return_func)($this->store); ($this->return_func)($this->store);
} }
} }
if ($this->status === self::STATUS_RULE_FAILED) $this->status = self::STATUS_NORMAL; if ($this->status === self::STATUS_RULE_FAILED) {
$this->status = self::STATUS_NORMAL;
}
//TODO:没有过滤before的false可能会导致一些问题先观望一下 //TODO:没有过滤before的false可能会导致一些问题先观望一下
} catch (InterruptException $e) { } catch (InterruptException $e) {
$this->store = $e->return_var; $this->store = $e->return_var;
$this->status = self::STATUS_INTERRUPTED; $this->status = self::STATUS_INTERRUPTED;
} catch (Exception | Error $e) { } catch (Exception|Error $e) {
$this->status = self::STATUS_EXCEPTION; $this->status = self::STATUS_EXCEPTION;
throw $e; throw $e;
} }
} }
/** /**
* @param mixed $v * @param mixed $v
* @param null $rule_func * @param null $rule_func
* @param mixed ...$params * @param mixed ...$params
* @return bool
* @throws InterruptException * @throws InterruptException
* @throws AnnotationException * @throws AnnotationException
* @return bool
* @noinspection PhpMissingReturnTypeInspection * @noinspection PhpMissingReturnTypeInspection
*/ */
public function dispatchEvent($v, $rule_func = null, ...$params) { public function dispatchEvent($v, $rule_func = null, ...$params)
{
$q_c = $v->class; $q_c = $v->class;
$q_f = $v->method; $q_f = $v->method;
if (($q_c ?? "") === "" && ($q_f instanceof Closure)) { if (($q_c ?? '') === '' && ($q_f instanceof Closure)) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 闭包函数的事件触发过程!"); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 闭包函数的事件触发过程!");
}
if ($rule_func !== null && !$rule_func($v)) { if ($rule_func !== null && !$rule_func($v)) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 闭包函数下的 ruleFunc 判断为 false, 拒绝执行此方法。"); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 闭包函数下的 ruleFunc 判断为 false, 拒绝执行此方法。");
}
$this->status = self::STATUS_RULE_FAILED; $this->status = self::STATUS_RULE_FAILED;
return false; return false;
} }
@@ -132,42 +171,55 @@ class EventDispatcher
$this->status = self::STATUS_NORMAL; $this->status = self::STATUS_NORMAL;
return true; return true;
} }
if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在判断 " . $q_c . "::" . $q_f . " 方法下的 ruleFunc ..."); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 正在判断 " . $q_c . '::' . $q_f . ' 方法下的 ruleFunc ...');
}
if ($rule_func !== null && !$rule_func($v)) { if ($rule_func !== null && !$rule_func($v)) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法下的 ruleFunc 判断为 false, 拒绝执行此方法。"); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] " . $q_c . '::' . $q_f . ' 方法下的 ruleFunc 判断为 false, 拒绝执行此方法。');
}
$this->status = self::STATUS_RULE_FAILED; $this->status = self::STATUS_RULE_FAILED;
return false; return false;
} }
if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法下的 ruleFunc 为真,继续执行方法本身 ..."); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] " . $q_c . '::' . $q_f . ' 方法下的 ruleFunc 为真,继续执行方法本身 ...');
}
if (isset(EventManager::$middleware_map[$q_c][$q_f])) { if (isset(EventManager::$middleware_map[$q_c][$q_f])) {
$middlewares = EventManager::$middleware_map[$q_c][$q_f]; $middlewares = EventManager::$middleware_map[$q_c][$q_f];
if ($this->log) Console::verbose("[事件分发{$this->eid}] " . $q_c . "::" . $q_f . " 方法还绑定了 Middleware" . implode(", ", array_map(function ($x) { return $x->middleware; }, $middlewares))); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] " . $q_c . '::' . $q_f . ' 方法还绑定了 Middleware' . implode(', ', array_map(function ($x) { return $x->middleware; }, $middlewares)));
}
$before_result = true; $before_result = true;
$r = []; $r = [];
foreach ($middlewares as $k => $middleware) { foreach ($middlewares as $k => $middleware) {
if (!isset(EventManager::$middlewares[$middleware->middleware])) { if (!isset(EventManager::$middlewares[$middleware->middleware])) {
if ((ZMConfig::get("global", "runtime")["middleware_error_policy"] ?? 1) == 1) if ((ZMConfig::get('global', 'runtime')['middleware_error_policy'] ?? 1) == 1) {
throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$middleware->middleware}\"!"); throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$middleware->middleware}\"!");
else }
continue; continue;
} }
$middleware_obj = EventManager::$middlewares[$middleware->middleware]; $middleware_obj = EventManager::$middlewares[$middleware->middleware];
$before = $middleware_obj["class"]; $before = $middleware_obj['class'];
//var_dump($middleware_obj); //var_dump($middleware_obj);
$r[$k] = new $before(); $r[$k] = new $before();
$r[$k]->class = $q_c; $r[$k]->class = $q_c;
$r[$k]->method = $q_f; $r[$k]->method = $q_f;
$r[$k]->middleware = $middleware; $r[$k]->middleware = $middleware;
$r[$k]->current_event = $v; $r[$k]->current_event = $v;
if (isset($middleware_obj["before"])) { if (isset($middleware_obj['before'])) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 存在前置事件,执行中 ..."); if ($this->log) {
$rs = $middleware_obj["before"]; Console::verbose("[事件分发{$this->eid}] Middleware 存在前置事件,执行中 ...");
$before_result = $r[$k]->$rs(...$params); }
$rs = $middleware_obj['before'];
$before_result = $r[$k]->{$rs}(...$params);
if ($before_result === false) { if ($before_result === false) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 前置事件为 false停止执行原事件开始执行下一事件。"); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] Middleware 前置事件为 false停止执行原事件开始执行下一事件。");
}
break; break;
} else { }
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 前置事件为 true继续执行原事件。"); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] Middleware 前置事件为 true继续执行原事件。");
} }
} }
} }
@@ -175,21 +227,31 @@ class EventDispatcher
try { try {
$q_o = ZMUtil::getModInstance($q_c); $q_o = ZMUtil::getModInstance($q_c);
$q_o->_running_annotation = $v; $q_o->_running_annotation = $v;
if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在执行方法 " . $q_c . "::" . $q_f . " ..."); if ($this->log) {
$this->store = $q_o->$q_f(...$params); Console::verbose("[事件分发{$this->eid}] 正在执行方法 " . $q_c . '::' . $q_f . ' ...');
}
$this->store = $q_o->{$q_f}(...$params);
} catch (Exception $e) { } catch (Exception $e) {
if ($e instanceof InterruptException) { if ($e instanceof InterruptException) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 检测到事件阻断调用,正在跳出事件分发器 ..."); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 检测到事件阻断调用,正在跳出事件分发器 ...");
}
throw $e; throw $e;
} }
if ($this->log) Console::verbose("[事件分发{$this->eid}] 方法 " . $q_c . "::" . $q_f . " 执行过程中抛出了异常,正在倒序查找 Middleware 中的捕获方法 ..."); if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 方法 " . $q_c . '::' . $q_f . ' 执行过程中抛出了异常,正在倒序查找 Middleware 中的捕获方法 ...');
}
for ($i = count($middlewares) - 1; $i >= 0; --$i) { for ($i = count($middlewares) - 1; $i >= 0; --$i) {
$middleware_obj = EventManager::$middlewares[$middlewares[$i]->middleware]; $middleware_obj = EventManager::$middlewares[$middlewares[$i]->middleware];
if (!isset($middleware_obj["exceptions"])) continue; if (!isset($middleware_obj['exceptions'])) {
foreach ($middleware_obj["exceptions"] as $name => $method) { continue;
}
foreach ($middleware_obj['exceptions'] as $name => $method) {
if ($e instanceof $name) { if ($e instanceof $name) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] 方法 " . $q_c . "::" . $q_f . " 的异常 " . get_class($e) . " 被 Middleware:" . $middlewares[$i] . " 下的 " . get_class($r[$i]) . "::" . $method . " 捕获。"); if ($this->log) {
$r[$i]->$method($e); Console::verbose("[事件分发{$this->eid}] 方法 " . $q_c . '::' . $q_f . ' 的异常 ' . get_class($e) . ' 被 Middleware:' . $middlewares[$i] . ' 下的 ' . get_class($r[$i]) . '::' . $method . ' 捕获。');
}
$r[$i]->{$method}($e);
self::interrupt(); self::interrupt();
} }
} }
@@ -199,10 +261,14 @@ class EventDispatcher
$cnts = count($middlewares) - 1; $cnts = count($middlewares) - 1;
for ($i = $cnts; $i >= 0; --$i) { for ($i = $cnts; $i >= 0; --$i) {
$middleware_obj = EventManager::$middlewares[$middlewares[$i]->middleware]; $middleware_obj = EventManager::$middlewares[$middlewares[$i]->middleware];
if (isset($middleware_obj["after"], $r[$i])) { if (isset($middleware_obj['after'], $r[$i])) {
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 存在后置事件,执行中 ..."); if ($this->log) {
$r[$i]->{$middleware_obj["after"]}(...$params); Console::verbose("[事件分发{$this->eid}] Middleware 存在后置事件,执行中 ...");
if ($this->log) Console::verbose("[事件分发{$this->eid}] Middleware 后置事件执行完毕!"); }
$r[$i]->{$middleware_obj['after']}(...$params);
if ($this->log) {
Console::verbose("[事件分发{$this->eid}] Middleware 后置事件执行完毕!");
}
} }
} }
$this->status = self::STATUS_NORMAL; $this->status = self::STATUS_NORMAL;
@@ -210,27 +276,24 @@ class EventDispatcher
} }
$this->status = self::STATUS_BEFORE_FAILED; $this->status = self::STATUS_BEFORE_FAILED;
return false; return false;
} else {
$q_o = ZMUtil::getModInstance($q_c);
$q_o->_running_annotation = $v;
if ($this->log) Console::verbose("[事件分发{$this->eid}] 正在执行方法 " . $q_c . "::" . $q_f . " ...");
$this->store = $q_o->$q_f(...$params);
$this->status = self::STATUS_NORMAL;
return true;
} }
$q_o = ZMUtil::getModInstance($q_c);
$q_o->_running_annotation = $v;
if ($this->log) {
Console::verbose("[事件分发{$this->eid}] 正在执行方法 " . $q_c . '::' . $q_f . ' ...');
}
$this->store = $q_o->{$q_f}(...$params);
$this->status = self::STATUS_NORMAL;
return true;
} }
/** public function getEid(): int
* @return int {
*/
public function getEid(): int {
return $this->eid; return $this->eid;
} }
/** public function getClass(): string
* @return string {
*/
public function getClass(): string {
return $this->class; return $this->class;
} }
} }

View File

@@ -1,9 +1,10 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event; namespace ZM\Event;
use Closure;
use Error; use Error;
use Exception; use Exception;
use Swoole\Timer; use Swoole\Timer;
@@ -19,15 +20,19 @@ use ZM\Store\ZMAtomic;
class EventManager class EventManager
{ {
public static $events = []; public static $events = [];
public static $middleware_map = []; public static $middleware_map = [];
public static $middlewares = []; public static $middlewares = [];
public static $req_mapping = []; public static $req_mapping = [];
public static function addEvent($event_name, ?AnnotationBase $event_obj) { public static function addEvent($event_name, ?AnnotationBase $event_obj)
if ($event_obj->method instanceof \Closure) { {
Console::debug("Adding event $event_name at @Anonymous"); if ($event_obj->method instanceof Closure) {
Console::debug("Adding event {$event_name} at @Anonymous");
} else { } else {
Console::debug("Adding event $event_name at " . ($event_obj->class) . ":" . ($event_obj->method)); Console::debug("Adding event {$event_name} at " . ($event_obj->class) . ':' . ($event_obj->method));
} }
self::$events[$event_name][] = $event_obj; self::$events[$event_name][] = $event_obj;
(new AnnotationParser())->sortByLevel(self::$events, $event_name); (new AnnotationParser())->sortByLevel(self::$events, $event_name);
@@ -36,7 +41,8 @@ class EventManager
/** /**
* @throws AnnotationException * @throws AnnotationException
*/ */
public static function loadEventByParser(AnnotationParser $parser) { public static function loadEventByParser(AnnotationParser $parser)
{
self::$events = $parser->generateAnnotationEvents(); self::$events = $parser->generateAnnotationEvents();
self::$middlewares = $parser->getMiddlewares(); self::$middlewares = $parser->getMiddlewares();
self::$middleware_map = $parser->getMiddlewareMap(); self::$middleware_map = $parser->getMiddlewareMap();
@@ -48,33 +54,36 @@ class EventManager
* 注册所有计时器给每个进程 * 注册所有计时器给每个进程
* @throws Exception * @throws Exception
*/ */
public static function registerTimerTick() { public static function registerTimerTick()
{
$dispatcher = new EventDispatcher(OnTick::class); $dispatcher = new EventDispatcher(OnTick::class);
foreach (self::$events[OnTick::class] ?? [] as $vss) { foreach (self::$events[OnTick::class] ?? [] as $vss) {
if (server()->worker_id !== $vss->worker_id && $vss->worker_id != -1) return; if (server()->worker_id !== $vss->worker_id && $vss->worker_id != -1) {
return;
}
//echo server()->worker_id.PHP_EOL; //echo server()->worker_id.PHP_EOL;
$plain_class = $vss->class; $plain_class = $vss->class;
Console::debug("Added Middleware-based timer: " . $plain_class . " -> " . $vss->method); Console::debug('Added Middleware-based timer: ' . $plain_class . ' -> ' . $vss->method);
Timer::tick($vss->tick_ms, function () use ($vss, $dispatcher) { Timer::tick($vss->tick_ms, function () use ($vss, $dispatcher) {
set_coroutine_params([]); set_coroutine_params([]);
if (ZMAtomic::get("stop_signal")->get() != 0) { if (ZMAtomic::get('stop_signal')->get() != 0) {
Timer::clearAll(); Timer::clearAll();
return; return;
} }
try { try {
$dispatcher->dispatchEvent($vss, null); $dispatcher->dispatchEvent($vss, null);
} catch (Exception $e) { } catch (Exception $e) {
Console::error(zm_internal_errcode("E00034") . "Uncaught error from TimerTick: " . $e->getMessage() . " at " . $e->getFile() . "({$e->getLine()})"); Console::error(zm_internal_errcode('E00034') . 'Uncaught error from TimerTick: ' . $e->getMessage() . ' at ' . $e->getFile() . "({$e->getLine()})");
} catch (Error $e) { } catch (Error $e) {
Console::error(zm_internal_errcode("E00034") . "Uncaught fatal error from TimerTick: " . $e->getMessage()); Console::error(zm_internal_errcode('E00034') . 'Uncaught fatal error from TimerTick: ' . $e->getMessage());
echo Console::setColor($e->getTraceAsString(), "gray"); echo Console::setColor($e->getTraceAsString(), 'gray');
Console::error("Please check your code!"); Console::error('Please check your code!');
} }
}); });
} }
$conf = ZMConfig::get("global", "worker_cache") ?? ["worker" => 0]; $conf = ZMConfig::get('global', 'worker_cache') ?? ['worker' => 0];
if (server()->worker_id == $conf["worker"]) { if (server()->worker_id == $conf['worker']) {
zm_timer_tick(ZMConfig::get("global", "light_cache")["auto_save_interval"] * 1000, function () { zm_timer_tick(ZMConfig::get('global', 'light_cache')['auto_save_interval'] * 1000, function () {
LightCache::savePersistence(); LightCache::savePersistence();
}); });
} }

View File

@@ -1,22 +1,23 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event; namespace ZM\Event;
use ZM\Annotation\AnnotationBase; use ZM\Annotation\AnnotationBase;
class EventTracer class EventTracer
{ {
/** /**
* 获取当前注解事件的注解类如CQCommand对象 * 获取当前注解事件的注解类如CQCommand对象
* @return AnnotationBase|null * @return null|AnnotationBase
*/ */
public static function getCurrentEvent() { public static function getCurrentEvent()
{
$list = debug_backtrace(); $list = debug_backtrace();
foreach ($list as $v) { foreach ($list as $v) {
if ((($v["object"] ?? null) instanceof EventDispatcher) && $v["function"] == "dispatchEvent") { if ((($v['object'] ?? null) instanceof EventDispatcher) && $v['function'] == 'dispatchEvent') {
return $v["args"][0]; return $v['args'][0];
} }
} }
return null; return null;
@@ -24,20 +25,24 @@ class EventTracer
/** /**
* 获取当前注解事件的中间件列表 * 获取当前注解事件的中间件列表
* @return array|mixed|null * @return null|array|mixed
*/ */
public static function getCurrentEventMiddlewares() { public static function getCurrentEventMiddlewares()
{
$current_event = self::getCurrentEvent(); $current_event = self::getCurrentEvent();
if (!isset($current_event->class, $current_event->method)) return null; if (!isset($current_event->class, $current_event->method)) {
return null;
}
return EventManager::$middleware_map[$current_event->class][$current_event->method] ?? []; return EventManager::$middleware_map[$current_event->class][$current_event->method] ?? [];
} }
public static function getEventTraceList() { public static function getEventTraceList()
{
$result = []; $result = [];
$list = debug_backtrace(); $list = debug_backtrace();
foreach ($list as $v) { foreach ($list as $v) {
if ((($v["object"] ?? null) instanceof EventDispatcher) && $v["function"] == "dispatchEvent") { if ((($v['object'] ?? null) instanceof EventDispatcher) && $v['function'] == 'dispatchEvent') {
$result[] = $v["args"][0]; $result[] = $v['args'][0];
} }
} }
return $result; return $result;

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event; namespace ZM\Event;
interface SwooleEvent interface SwooleEvent
{ {
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Swoole\Process; use Swoole\Process;
use Swoole\WebSocket\Server; use Swoole\WebSocket\Server;
use ZM\Annotation\Swoole\SwooleHandler; use ZM\Annotation\Swoole\SwooleHandler;
@@ -13,17 +13,19 @@ use ZM\Event\SwooleEvent;
/** /**
* Class OnBeforeReload * Class OnBeforeReload
* @package ZM\Event\SwooleEvent
* @SwooleHandler("BeforeReload") * @SwooleHandler("BeforeReload")
*/ */
class OnBeforeReload implements SwooleEvent class OnBeforeReload implements SwooleEvent
{ {
public function onCall(Server $server) { public function onCall(Server $server)
Console::info(Console::setColor("Reloading server...", "gold")); {
Console::info(Console::setColor('Reloading server...', 'gold'));
for ($i = 0; $i < ZM_WORKER_NUM; ++$i) { for ($i = 0; $i < ZM_WORKER_NUM; ++$i) {
Process::kill(zm_atomic("_#worker_" . $i)->get(), SIGUSR1); Process::kill(zm_atomic('_#worker_' . $i)->get(), SIGUSR1);
}
$conf = ZMConfig::get('global', 'runtime')['reload_delay_time'] ?? 800;
if ($conf !== 0) {
usleep($conf * 1000);
} }
$conf = ZMConfig::get("global", "runtime")["reload_delay_time"] ?? 800;
if ($conf !== 0) usleep($conf * 1000);
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Error; use Error;
use Exception; use Exception;
use Swoole\Coroutine; use Swoole\Coroutine;
@@ -20,52 +20,53 @@ use ZM\Store\LightCacheInside;
/** /**
* Class OnClose * Class OnClose
* @package ZM\Event\SwooleEvent
* @SwooleHandler("close") * @SwooleHandler("close")
*/ */
class OnClose implements SwooleEvent class OnClose implements SwooleEvent
{ {
/** @noinspection PhpUnreachableStatementInspection */ public function onCall($server, $fd)
public function onCall($server, $fd) { {
unset(Context::$context[Coroutine::getCid()]); unset(Context::$context[Coroutine::getCid()]);
Console::debug("Calling Swoole \"close\" event from fd=" . $fd); Console::debug('Calling Swoole "close" event from fd=' . $fd);
$conn = ManagerGM::get($fd); $conn = ManagerGM::get($fd);
if ($conn === null) return; if ($conn === null) {
set_coroutine_params(["server" => $server, "connection" => $conn, "fd" => $fd]); return;
}
set_coroutine_params(['server' => $server, 'connection' => $conn, 'fd' => $fd]);
$dispatcher1 = new EventDispatcher(OnCloseEvent::class); $dispatcher1 = new EventDispatcher(OnCloseEvent::class);
$dispatcher1->setRuleFunction(function ($v) { $dispatcher1->setRuleFunction(function ($v) {
return $v->connect_type == ctx()->getConnection()->getName() && eval("return " . $v->getRule() . ";"); return $v->connect_type == ctx()->getConnection()->getName() && eval('return ' . $v->getRule() . ';');
}); });
$dispatcher = new EventDispatcher(OnSwooleEvent::class); $dispatcher = new EventDispatcher(OnSwooleEvent::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
if ($v->getRule() == '') { if ($v->getRule() == '') {
return strtolower($v->type) == 'close'; return strtolower($v->type) == 'close';
} else {
/** @noinspection PhpUnreachableStatementInspection */
if (strtolower($v->type) == 'close' && eval("return " . $v->getRule() . ";")) return true;
else return false;
} }
if (strtolower($v->type) == 'close' && eval('return ' . $v->getRule() . ';')) {
return true;
}
return false;
}); });
try { try {
$obb_onebot = ZMConfig::get("global", "onebot") ?? $obb_onebot = ZMConfig::get('global', 'onebot') ??
ZMConfig::get("global", "modules")["onebot"] ?? ZMConfig::get('global', 'modules')['onebot'] ??
["status" => true, "single_bot_mode" => false, "message_level" => 99999]; ['status' => true, 'single_bot_mode' => false, 'message_level' => 99999];
if ($conn->getName() === 'qq' && $obb_onebot["status"] === true) { if ($conn->getName() === 'qq' && $obb_onebot['status'] === true) {
if ($obb_onebot["single_bot_mode"]) { if ($obb_onebot['single_bot_mode']) {
LightCacheInside::set("connect", "conn_fd", -1); LightCacheInside::set('connect', 'conn_fd', -1);
} }
} }
$dispatcher1->dispatchEvents($conn); $dispatcher1->dispatchEvents($conn);
$dispatcher->dispatchEvents($conn); $dispatcher->dispatchEvents($conn);
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00016") . "Uncaught exception " . get_class($e) . " when calling \"close\": " . $error_msg); Console::error(zm_internal_errcode('E00016') . 'Uncaught exception ' . get_class($e) . ' when calling "close": ' . $error_msg);
Console::trace(); Console::trace();
} catch (Error $e) { } catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00016") . "Uncaught " . get_class($e) . " when calling \"close\": " . $error_msg); Console::error(zm_internal_errcode('E00016') . 'Uncaught ' . get_class($e) . ' when calling "close": ' . $error_msg);
Console::trace(); Console::trace();
} }
ManagerGM::popConnect($fd); ManagerGM::popConnect($fd);

View File

@@ -1,11 +1,15 @@
<?php /** @noinspection PhpUnusedParameterInspection */ <?php
/** @noinspection PhpComposerExtensionStubsInspection */ /**
* @noinspection PhpPropertyOnlyWrittenInspection
* @noinspection PhpUnusedParameterInspection
* @noinspection PhpComposerExtensionStubsInspection
*/
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Error; use Error;
use Exception; use Exception;
use Swoole\Event; use Swoole\Event;
@@ -24,50 +28,51 @@ use ZM\Utils\ZMUtil;
/** /**
* Class OnManagerStart * Class OnManagerStart
* @package ZM\Event\SwooleEvent
* @SwooleHandler("ManagerStart") * @SwooleHandler("ManagerStart")
*/ */
class OnManagerStart implements SwooleEvent class OnManagerStart implements SwooleEvent
{ {
private static $last_hash = ""; private static $last_hash = '';
private static $watch = -1; private static $watch = -1;
public function onCall(Server $server) { public function onCall(Server $server)
Console::debug("Calling onManagerStart event(1)"); {
if (!Framework::$argv["disable-safe-exit"]) { Console::debug('Calling onManagerStart event(1)');
if (!Framework::$argv['disable-safe-exit']) {
SignalListener::signalManager(); SignalListener::signalManager();
} }
Framework::saveProcessState(ZM_PROCESS_MANAGER, $server->manager_pid); Framework::saveProcessState(ZM_PROCESS_MANAGER, $server->manager_pid);
ProcessManager::createUserProcess('monitor', function() use ($server){ ProcessManager::createUserProcess('monitor', function () use ($server) {
Process::signal(SIGINT, function() { Process::signal(SIGINT, function () {
Console::success("用户进程检测到了Ctrl+C"); Console::success('用户进程检测到了Ctrl+C');
}); });
if (Framework::$argv["watch"]) { if (Framework::$argv['watch']) {
if (extension_loaded('inotify')) { if (extension_loaded('inotify')) {
Console::info("Enabled File watcher, framework will reload automatically."); Console::info('Enabled File watcher, framework will reload automatically.');
/** @noinspection PhpUndefinedFieldInspection */ /* @noinspection PhpUndefinedFieldInspection */
Framework::$server->inotify = $fd = inotify_init(); Framework::$server->inotify = $fd = inotify_init();
$this->addWatcher(DataProvider::getSourceRootDir() . "/src", $fd); $this->addWatcher(DataProvider::getSourceRootDir() . '/src', $fd);
Event::add($fd, function () use ($fd) { Event::add($fd, function () use ($fd) {
$r = inotify_read($fd); $r = inotify_read($fd);
Console::verbose("File updated: " . $r[0]["name"]); Console::verbose('File updated: ' . $r[0]['name']);
ZMUtil::reload(); ZMUtil::reload();
}); });
Framework::$argv["polling-watch"] = false; // 如果开启了inotify则关闭轮询热更新 Framework::$argv['polling-watch'] = false; // 如果开启了inotify则关闭轮询热更新
} else { } else {
Console::warning(zm_internal_errcode("E00024") . "你还没有安装或启用 inotify 扩展,将默认使用轮询检测模式开启热更新!"); Console::warning(zm_internal_errcode('E00024') . '你还没有安装或启用 inotify 扩展,将默认使用轮询检测模式开启热更新!');
Framework::$argv["polling-watch"] = true; Framework::$argv['polling-watch'] = true;
} }
} }
if (Framework::$argv["polling-watch"]) { if (Framework::$argv['polling-watch']) {
self::$watch = swoole_timer_tick(3000, function () use ($server) { self::$watch = swoole_timer_tick(3000, function () use ($server) {
$data = (DataProvider::scanDirFiles(DataProvider::getSourceRootDir() . '/src/')); $data = (DataProvider::scanDirFiles(DataProvider::getSourceRootDir() . '/src/'));
$hash = md5(""); $hash = md5('');
foreach ($data as $file) { foreach ($data as $file) {
$hash = md5($hash . md5_file($file)); $hash = md5($hash . md5_file($file));
} }
if (self::$last_hash == "") { if (self::$last_hash == '') {
self::$last_hash = $hash; self::$last_hash = $hash;
} elseif (self::$last_hash !== $hash) { } elseif (self::$last_hash !== $hash) {
self::$last_hash = $hash; self::$last_hash = $hash;
@@ -75,8 +80,8 @@ class OnManagerStart implements SwooleEvent
} }
}); });
} }
if (Framework::$argv["interact"]) { if (Framework::$argv['interact']) {
Console::info("Interact mode"); Console::info('Interact mode');
ZMBuf::$terminal = $r = STDIN; ZMBuf::$terminal = $r = STDIN;
Event::add($r, function () use ($r) { Event::add($r, function () use ($r) {
$fget = fgets($r); $fget = fgets($r);
@@ -85,13 +90,15 @@ class OnManagerStart implements SwooleEvent
return; return;
} }
$var = trim($fget); $var = trim($fget);
if ($var == "stop") Event::del($r); if ($var == 'stop') {
Event::del($r);
}
try { try {
Terminal::executeCommand($var); Terminal::executeCommand($var);
} catch (Exception $e) { } catch (Exception $e) {
Console::error(zm_internal_errcode("E00025") . "Uncaught exception " . get_class($e) . ": " . $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"); Console::error(zm_internal_errcode('E00025') . 'Uncaught exception ' . get_class($e) . ': ' . $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')');
} catch (Error $e) { } catch (Error $e) {
Console::error(zm_internal_errcode("E00025") . "Uncaught error " . get_class($e) . ": " . $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"); Console::error(zm_internal_errcode('E00025') . 'Uncaught error ' . get_class($e) . ': ' . $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')');
} }
}); });
} }
@@ -106,19 +113,20 @@ class OnManagerStart implements SwooleEvent
}); });
$dispatcher->dispatchEvents($server); $dispatcher->dispatchEvents($server);
*/ */
Console::verbose("进程 Manager 已启动"); Console::verbose('进程 Manager 已启动');
} }
private function addWatcher($maindir, $fd) { private function addWatcher($maindir, $fd)
{
$dir = scandir($maindir); $dir = scandir($maindir);
if ($dir[0] == ".") { if ($dir[0] == '.') {
unset($dir[0], $dir[1]); unset($dir[0], $dir[1]);
} }
foreach ($dir as $subdir) { foreach ($dir as $subdir) {
if (is_dir($maindir . "/" . $subdir)) { if (is_dir($maindir . '/' . $subdir)) {
Console::debug("添加监听目录:" . $maindir . "/" . $subdir); Console::debug('添加监听目录:' . $maindir . '/' . $subdir);
inotify_add_watch($fd, $maindir . "/" . $subdir, IN_ATTRIB | IN_ISDIR); inotify_add_watch($fd, $maindir . '/' . $subdir, IN_ATTRIB | IN_ISDIR);
$this->addWatcher($maindir . "/" . $subdir, $fd); $this->addWatcher($maindir . '/' . $subdir, $fd);
} }
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Swoole\Process; use Swoole\Process;
use ZM\Annotation\Swoole\SwooleHandler; use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Console\Console; use ZM\Console\Console;
@@ -13,7 +13,6 @@ use ZM\Utils\Manager\ProcessManager;
/** /**
* Class OnManagerStop * Class OnManagerStop
* @package ZM\Event\SwooleEvent
* @SwooleHandler("ManagerStop") * @SwooleHandler("ManagerStop")
*/ */
class OnManagerStop implements SwooleEvent class OnManagerStop implements SwooleEvent
@@ -21,9 +20,11 @@ class OnManagerStop implements SwooleEvent
public function onCall() public function onCall()
{ {
foreach (ProcessManager::$user_process as $v) { foreach (ProcessManager::$user_process as $v) {
if (posix_getsid($v->pid) !== false) Process::kill($v->pid, SIGTERM); if (posix_getsid($v->pid) !== false) {
Process::kill($v->pid, SIGTERM);
}
} }
Console::verbose("进程 Manager 已停止!"); Console::verbose('进程 Manager 已停止!');
Framework::removeProcessState(ZM_PROCESS_MANAGER); Framework::removeProcessState(ZM_PROCESS_MANAGER);
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Error; use Error;
use Exception; use Exception;
use Swoole\Coroutine; use Swoole\Coroutine;
@@ -20,34 +20,36 @@ use ZM\Event\SwooleEvent;
/** /**
* Class OnMessage * Class OnMessage
* @package ZM\Event\SwooleEvent
* @SwooleHandler("message") * @SwooleHandler("message")
*/ */
class OnMessage implements SwooleEvent class OnMessage implements SwooleEvent
{ {
public function onCall($server, Frame $frame) { public function onCall($server, Frame $frame)
Console::debug("Calling Swoole \"message\" from fd=" . $frame->fd . ": " . TermColor::ITALIC . $frame->data . TermColor::RESET); {
Console::debug('Calling Swoole "message" from fd=' . $frame->fd . ': ' . TermColor::ITALIC . $frame->data . TermColor::RESET);
unset(Context::$context[Coroutine::getCid()]); unset(Context::$context[Coroutine::getCid()]);
$conn = ManagerGM::get($frame->fd); $conn = ManagerGM::get($frame->fd);
set_coroutine_params(["server" => $server, "frame" => $frame, "connection" => $conn]); set_coroutine_params(['server' => $server, 'frame' => $frame, 'connection' => $conn]);
$dispatcher1 = new EventDispatcher(OnMessageEvent::class); $dispatcher1 = new EventDispatcher(OnMessageEvent::class);
$dispatcher1->setRuleFunction(function ($v) { $dispatcher1->setRuleFunction(function ($v) {
if ($v->getRule() == '') return true; if ($v->getRule() == '') {
else return eval("return " . $v->getRule() . ";"); return true;
}
return eval('return ' . $v->getRule() . ';');
}); });
$dispatcher = new EventDispatcher(OnSwooleEvent::class); $dispatcher = new EventDispatcher(OnSwooleEvent::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
if ($v->getRule() == '') { if ($v->getRule() == '') {
return strtolower($v->type) == 'message'; return strtolower($v->type) == 'message';
} else {
/** @noinspection PhpUnreachableStatementInspection
* @noinspection RedundantSuppression
*/
if (strtolower($v->type) == 'message' && eval("return " . $v->getRule() . ";")) return true;
else return false;
} }
/* @noinspection PhpUnreachableStatementInspection
* @noinspection RedundantSuppression
*/
if (strtolower($v->type) == 'message' && eval('return ' . $v->getRule() . ';')) {
return true;
}
return false;
}); });
try { try {
//$starttime = microtime(true); //$starttime = microtime(true);
@@ -55,14 +57,13 @@ class OnMessage implements SwooleEvent
$dispatcher->dispatchEvents($conn); $dispatcher->dispatchEvents($conn);
//Console::success("Used ".round((microtime(true) - $starttime) * 1000, 3)." ms!"); //Console::success("Used ".round((microtime(true) - $starttime) * 1000, 3)." ms!");
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00017") . "Uncaught exception " . get_class($e) . " when calling \"message\": " . $error_msg); Console::error(zm_internal_errcode('E00017') . 'Uncaught exception ' . get_class($e) . ' when calling "message": ' . $error_msg);
Console::trace(); Console::trace();
} catch (Error $e) { } catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00017") . "Uncaught " . get_class($e) . " when calling \"message\": " . $error_msg); Console::error(zm_internal_errcode('E00017') . 'Uncaught ' . get_class($e) . ' when calling "message": ' . $error_msg);
Console::trace(); Console::trace();
} }
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Closure; use Closure;
use Error; use Error;
use Exception; use Exception;
@@ -22,70 +22,70 @@ use ZM\Store\LightCacheInside;
/** /**
* Class OnOpen * Class OnOpen
* @package ZM\Event\SwooleEvent
* @SwooleHandler("open") * @SwooleHandler("open")
*/ */
class OnOpen implements SwooleEvent class OnOpen implements SwooleEvent
{ {
/** @noinspection PhpUnreachableStatementInspection */ public function onCall($server, Request $request)
public function onCall($server, Request $request) { {
Console::debug("Calling Swoole \"open\" event from fd=" . $request->fd); Console::debug('Calling Swoole "open" event from fd=' . $request->fd);
unset(Context::$context[Coroutine::getCid()]); unset(Context::$context[Coroutine::getCid()]);
$type = strtolower($request->header["x-client-role"] ?? $request->get["type"] ?? ""); $type = strtolower($request->header['x-client-role'] ?? $request->get['type'] ?? '');
$access_token = explode(" ", $request->header["authorization"] ?? "")[1] ?? $request->get["token"] ?? ""; $access_token = explode(' ', $request->header['authorization'] ?? '')[1] ?? $request->get['token'] ?? '';
$token = ZMConfig::get("global", "access_token"); $token = ZMConfig::get('global', 'access_token');
if ($token instanceof Closure) { if ($token instanceof Closure) {
if (!$token($access_token)) { if (!$token($access_token)) {
$server->close($request->fd); $server->close($request->fd);
Console::warning(zm_internal_errcode("E00018") . "Unauthorized access_token: " . $access_token); Console::warning(zm_internal_errcode('E00018') . 'Unauthorized access_token: ' . $access_token);
return; return;
} }
} elseif (is_string($token)) { } elseif (is_string($token)) {
if ($access_token !== $token && $token !== "") { if ($access_token !== $token && $token !== '') {
$server->close($request->fd); $server->close($request->fd);
Console::warning(zm_internal_errcode("E00019") . "Unauthorized access_token: " . $access_token); Console::warning(zm_internal_errcode('E00019') . 'Unauthorized access_token: ' . $access_token);
return; return;
} }
} }
$type_conn = ManagerGM::getTypeClassName($type); $type_conn = ManagerGM::getTypeClassName($type);
ManagerGM::pushConnect($request->fd, $type_conn); ManagerGM::pushConnect($request->fd, $type_conn);
$conn = ManagerGM::get($request->fd); $conn = ManagerGM::get($request->fd);
set_coroutine_params(["server" => $server, "request" => $request, "connection" => $conn, "fd" => $request->fd]); set_coroutine_params(['server' => $server, 'request' => $request, 'connection' => $conn, 'fd' => $request->fd]);
$conn->setOption("connect_id", strval($request->header["x-self-id"] ?? "")); $conn->setOption('connect_id', strval($request->header['x-self-id'] ?? ''));
$dispatcher1 = new EventDispatcher(OnOpenEvent::class); $dispatcher1 = new EventDispatcher(OnOpenEvent::class);
$dispatcher1->setRuleFunction(function ($v) { $dispatcher1->setRuleFunction(function ($v) {
return ctx()->getConnection()->getName() == $v->connect_type && eval("return " . $v->getRule() . ";"); return ctx()->getConnection()->getName() == $v->connect_type && eval('return ' . $v->getRule() . ';');
}); });
$dispatcher = new EventDispatcher(OnSwooleEvent::class); $dispatcher = new EventDispatcher(OnSwooleEvent::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
if ($v->getRule() == '') { if ($v->getRule() == '') {
return strtolower($v->type) == 'open'; return strtolower($v->type) == 'open';
} else {
if (strtolower($v->type) == 'open' && eval("return " . $v->getRule() . ";")) return true;
else return false;
} }
if (strtolower($v->type) == 'open' && eval('return ' . $v->getRule() . ';')) {
return true;
}
return false;
}); });
try { try {
$obb_onebot = ZMConfig::get("global", "onebot") ?? $obb_onebot = ZMConfig::get('global', 'onebot') ??
ZMConfig::get("global", "modules")["onebot"] ?? ZMConfig::get('global', 'modules')['onebot'] ??
["status" => true, "single_bot_mode" => false, "message_level" => 99]; ['status' => true, 'single_bot_mode' => false, 'message_level' => 99];
$onebot_status = $obb_onebot["status"]; $onebot_status = $obb_onebot['status'];
if ($conn->getName() === 'qq' && $onebot_status === true) { if ($conn->getName() === 'qq' && $onebot_status === true) {
if ($obb_onebot["single_bot_mode"]) { if ($obb_onebot['single_bot_mode']) {
LightCacheInside::set("connect", "conn_fd", $request->fd); LightCacheInside::set('connect', 'conn_fd', $request->fd);
} }
} }
$dispatcher1->dispatchEvents($conn); $dispatcher1->dispatchEvents($conn);
$dispatcher->dispatchEvents($conn); $dispatcher->dispatchEvents($conn);
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00020") . "Uncaught exception " . get_class($e) . " when calling \"open\": " . $error_msg); Console::error(zm_internal_errcode('E00020') . 'Uncaught exception ' . get_class($e) . ' when calling "open": ' . $error_msg);
Console::trace(); Console::trace();
} catch (Error $e) { } catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00020") . "Uncaught " . get_class($e) . " when calling \"open\": " . $error_msg); Console::error(zm_internal_errcode('E00020') . 'Uncaught ' . get_class($e) . ' when calling "open": ' . $error_msg);
Console::trace(); Console::trace();
} }
} }

View File

@@ -1,9 +1,11 @@
<?php /** @noinspection PhpUnusedParameterInspection */ <?php
/** @noinspection PhpUnusedParameterInspection */
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Error; use Error;
use Exception; use Exception;
use Swoole\Server; use Swoole\Server;
@@ -14,22 +16,22 @@ use ZM\Utils\Manager\WorkerManager;
/** /**
* Class OnPipeMessage * Class OnPipeMessage
* @package ZM\Event\SwooleEvent
* @SwooleHandler("PipeMessage") * @SwooleHandler("PipeMessage")
*/ */
class OnPipeMessage implements SwooleEvent class OnPipeMessage implements SwooleEvent
{ {
public function onCall(Server $server, $src_worker_id, $data) { public function onCall(Server $server, $src_worker_id, $data)
{
$data = json_decode($data, true); $data = json_decode($data, true);
try { try {
WorkerManager::workerAction($src_worker_id, $data); WorkerManager::workerAction($src_worker_id, $data);
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00021") . "Uncaught exception " . get_class($e) . " when calling \"pipeMessage\": " . $error_msg); Console::error(zm_internal_errcode('E00021') . 'Uncaught exception ' . get_class($e) . ' when calling "pipeMessage": ' . $error_msg);
Console::trace(); Console::trace();
} catch (Error $e) { } catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00021") . "Uncaught " . get_class($e) . " when calling \"pipeMessage\": " . $error_msg); Console::error(zm_internal_errcode('E00021') . 'Uncaught ' . get_class($e) . ' when calling "pipeMessage": ' . $error_msg);
Console::trace(); Console::trace();
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Error; use Error;
use Exception; use Exception;
use Swoole\Coroutine; use Swoole\Coroutine;
@@ -23,54 +23,55 @@ use ZM\Utils\HttpUtil;
/** /**
* Class OnRequest * Class OnRequest
* @package ZM\Event\SwooleEvent
* @SwooleHandler("request") * @SwooleHandler("request")
*/ */
class OnRequest implements SwooleEvent class OnRequest implements SwooleEvent
{ {
public function onCall(?Request $request, ?\Swoole\Http\Response $response) { public function onCall(?Request $request, ?\Swoole\Http\Response $response)
{
$response = new Response($response); $response = new Response($response);
foreach (ZMConfig::get("global")["http_header"] as $k => $v) { foreach (ZMConfig::get('global')['http_header'] as $k => $v) {
$response->setHeader($k, $v); $response->setHeader($k, $v);
} }
unset(Context::$context[Coroutine::getCid()]); unset(Context::$context[Coroutine::getCid()]);
Console::debug("Calling Swoole \"request\" event from fd=" . $request->fd); Console::debug('Calling Swoole "request" event from fd=' . $request->fd);
set_coroutine_params(["request" => $request, "response" => $response]); set_coroutine_params(['request' => $request, 'response' => $response]);
$dis1 = new EventDispatcher(OnRequestEvent::class); $dis1 = new EventDispatcher(OnRequestEvent::class);
$dis1->setRuleFunction(function ($v) { $dis1->setRuleFunction(function ($v) {
/** @noinspection PhpUnreachableStatementInspection */ return eval('return ' . $v->getRule() . ';') ? true : false;
return eval("return " . $v->getRule() . ";") ? true : false;
}); });
$dis = new EventDispatcher(OnSwooleEvent::class); $dis = new EventDispatcher(OnSwooleEvent::class);
$dis->setRuleFunction(function ($v) { $dis->setRuleFunction(function ($v) {
if ($v->getRule() == '') { if ($v->getRule() == '') {
return strtolower($v->type) == 'request'; return strtolower($v->type) == 'request';
} else {
/** @noinspection PhpUnreachableStatementInspection */
if (strtolower($v->type) == 'request' && eval("return " . $v->getRule() . ";")) return true;
else return false;
} }
if (strtolower($v->type) == 'request' && eval('return ' . $v->getRule() . ';')) {
return true;
}
return false;
}); });
try { try {
$dis1->dispatchEvents($request, $response); $dis1->dispatchEvents($request, $response);
$dis->dispatchEvents($request, $response); $dis->dispatchEvents($request, $response);
if ($dis->status === EventDispatcher::STATUS_NORMAL && $dis1->status === EventDispatcher::STATUS_NORMAL) { if ($dis->status === EventDispatcher::STATUS_NORMAL && $dis1->status === EventDispatcher::STATUS_NORMAL) {
$result = HttpUtil::parseUri($request, $response, $request->server["request_uri"], $node, $params); $result = HttpUtil::parseUri($request, $response, $request->server['request_uri'], $node, $params);
if ($result === true) { if ($result === true) {
ctx()->setCache("params", $params); ctx()->setCache('params', $params);
$dispatcher = new EventDispatcher(RequestMapping::class); $dispatcher = new EventDispatcher(RequestMapping::class);
$div = new RequestMapping(); $div = new RequestMapping();
$div->route = $node["route"]; $div->route = $node['route'];
$div->params = $params; $div->params = $params;
$div->method = $node["method"]; $div->method = $node['method'];
$div->request_method = $node["request_method"]; $div->request_method = $node['request_method'];
$div->class = $node["class"]; $div->class = $node['class'];
//Console::success("正在执行路由:".$node["method"]); //Console::success("正在执行路由:".$node["method"]);
$dispatcher->dispatchEvent($div, null, $params, $request, $response); $dispatcher->dispatchEvent($div, null, $params, $request, $response);
if (is_string($dispatcher->store) && !$response->isEnd()) $response->end($dispatcher->store); if (is_string($dispatcher->store) && !$response->isEnd()) {
$response->end($dispatcher->store);
}
} }
} }
if (!$response->isEnd()) { if (!$response->isEnd()) {
@@ -81,31 +82,35 @@ class OnRequest implements SwooleEvent
// do nothing // do nothing
} catch (Exception $e) { } catch (Exception $e) {
$response->status(500); $response->status(500);
Console::info($request->server["remote_addr"] . ":" . $request->server["remote_port"] . Console::info(
" [" . $response->getStatusCode() . "] " . $request->server["request_uri"] $request->server['remote_addr'] . ':' . $request->server['remote_port'] .
' [' . $response->getStatusCode() . '] ' . $request->server['request_uri']
); );
if (!$response->isEnd()) { if (!$response->isEnd()) {
if (ZMConfig::get("global", "debug_mode")) if (ZMConfig::get('global', 'debug_mode')) {
$response->end(zm_internal_errcode("E00023") . "Internal server exception: " . $e->getMessage()); $response->end(zm_internal_errcode('E00023') . 'Internal server exception: ' . $e->getMessage());
else } else {
$response->end(zm_internal_errcode("E00023") . "Internal server error."); $response->end(zm_internal_errcode('E00023') . 'Internal server error.');
}
} }
Console::error(zm_internal_errcode("E00023") . "Internal server exception (500), caused by " . get_class($e) . ": " . $e->getMessage()); Console::error(zm_internal_errcode('E00023') . 'Internal server exception (500), caused by ' . get_class($e) . ': ' . $e->getMessage());
Console::log($e->getTraceAsString(), "gray"); Console::log($e->getTraceAsString(), 'gray');
} catch (Error $e) { } catch (Error $e) {
$response->status(500); $response->status(500);
Console::info($request->server["remote_addr"] . ":" . $request->server["remote_port"] . Console::info(
" [" . $response->getStatusCode() . "] " . $request->server["request_uri"] $request->server['remote_addr'] . ':' . $request->server['remote_port'] .
' [' . $response->getStatusCode() . '] ' . $request->server['request_uri']
); );
if (!$response->isEnd()) { if (!$response->isEnd()) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
if (ZMConfig::get("global", "debug_mode")) if (ZMConfig::get('global', 'debug_mode')) {
$response->end(zm_internal_errcode("E00023") . "Internal server error: " . $error_msg); $response->end(zm_internal_errcode('E00023') . 'Internal server error: ' . $error_msg);
else } else {
$response->end(zm_internal_errcode("E00023") . "Internal server error."); $response->end(zm_internal_errcode('E00023') . 'Internal server error.');
}
} }
Console::error(zm_internal_errcode("E00023") . "Internal server error (500), caused by " . get_class($e) . ": " . $e->getMessage()); Console::error(zm_internal_errcode('E00023') . 'Internal server error (500), caused by ' . get_class($e) . ': ' . $e->getMessage());
Console::log($e->getTraceAsString(), "gray"); Console::log($e->getTraceAsString(), 'gray');
} }
} }
} }

View File

@@ -1,9 +1,11 @@
<?php /** @noinspection PhpUnusedParameterInspection */ <?php
/** @noinspection PhpUnusedParameterInspection */
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Swoole\Server; use Swoole\Server;
use ZM\Annotation\Swoole\SwooleHandler; use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Console\Console; use ZM\Console\Console;
@@ -13,13 +15,13 @@ use ZM\Utils\DataProvider;
/** /**
* Class OnShutdown * Class OnShutdown
* @package ZM\Event\SwooleEvent
* @SwooleHandler("shutdown") * @SwooleHandler("shutdown")
*/ */
class OnShutdown implements SwooleEvent class OnShutdown implements SwooleEvent
{ {
public function onCall(Server $server) { public function onCall(Server $server)
Console::verbose("正在关闭 Master 进程pid=" . posix_getpid()); {
Console::verbose('正在关闭 Master 进程pid=' . posix_getpid());
Framework::removeProcessState(ZM_PROCESS_MASTER); Framework::removeProcessState(ZM_PROCESS_MASTER);
if (DataProvider::scanDirFiles(_zm_pid_dir()) == []) { if (DataProvider::scanDirFiles(_zm_pid_dir()) == []) {
rmdir(_zm_pid_dir()); rmdir(_zm_pid_dir());

View File

@@ -1,33 +1,32 @@
<?php /** @noinspection PhpComposerExtensionStubsInspection */ <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Swoole\Server; use Swoole\Server;
use ZM\Annotation\Swoole\SwooleHandler; use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\Console\Console; use ZM\Console\Console;
use ZM\Event\SwooleEvent; use ZM\Event\SwooleEvent;
use ZM\Framework; use ZM\Framework;
use ZM\Utils\DataProvider;
use ZM\Utils\SignalListener; use ZM\Utils\SignalListener;
/** /**
* Class OnStart * Class OnStart
* @package ZM\Event\SwooleEvent
* @SwooleHandler("start") * @SwooleHandler("start")
*/ */
class OnStart implements SwooleEvent class OnStart implements SwooleEvent
{ {
public function onCall(Server $server) { public function onCall(Server $server)
Console::debug("Calling onStart event(1)"); {
if (!Framework::$argv["disable-safe-exit"]) { Console::debug('Calling onStart event(1)');
if (!Framework::$argv['disable-safe-exit']) {
SignalListener::signalMaster($server); SignalListener::signalMaster($server);
} }
Framework::saveProcessState(ZM_PROCESS_MASTER, $server->master_pid, [ Framework::saveProcessState(ZM_PROCESS_MASTER, $server->master_pid, [
'stdout' => ZMConfig::get("global")["swoole"]["log_file"], 'stdout' => ZMConfig::get('global')['swoole']['log_file'],
'daemon' => (bool)Framework::$argv["daemon"] 'daemon' => (bool) Framework::$argv['daemon'],
]); ]);
} }
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Error; use Error;
use Exception; use Exception;
use Swoole\Server; use Swoole\Server;
@@ -17,41 +17,38 @@ use ZM\Event\SwooleEvent;
/** /**
* Class OnTask * Class OnTask
* @package ZM\Event\SwooleEvent
* @SwooleHandler("task") * @SwooleHandler("task")
*/ */
class OnTask implements SwooleEvent class OnTask implements SwooleEvent
{ {
/** /**
* @noinspection PhpUnreachableStatementInspection
* @noinspection PhpUnusedParameterInspection * @noinspection PhpUnusedParameterInspection
* @param Server|null $server
* @param Task $task
*/ */
public function onCall(?Server $server, Task $task) { public function onCall(?Server $server, Task $task)
if (isset($task->data["task"])) { {
if (isset($task->data['task'])) {
$dispatcher = new EventDispatcher(\ZM\Annotation\Swoole\OnTask::class); $dispatcher = new EventDispatcher(\ZM\Annotation\Swoole\OnTask::class);
$dispatcher->setRuleFunction(function ($v) use ($task) { $dispatcher->setRuleFunction(function ($v) use ($task) {
/** @var \ZM\Annotation\Swoole\OnTask $v */ /* @var \ZM\Annotation\Swoole\OnTask $v */
return $v->task_name == $task->data["task"]; return $v->task_name == $task->data['task'];
}); });
$dispatcher->setReturnFunction(function ($return) { $dispatcher->setReturnFunction(function ($return) {
EventDispatcher::interrupt($return); EventDispatcher::interrupt($return);
}); });
$params = $task->data["params"]; $params = $task->data['params'];
try { try {
$dispatcher->dispatchEvents(...$params); $dispatcher->dispatchEvents(...$params);
} catch (Throwable $e) { } catch (Throwable $e) {
$finish["throw"] = $e; $finish['throw'] = $e;
} }
if ($dispatcher->status === EventDispatcher::STATUS_EXCEPTION) { if ($dispatcher->status === EventDispatcher::STATUS_EXCEPTION) {
$finish["result"] = null; $finish['result'] = null;
$finish["retcode"] = -1; $finish['retcode'] = -1;
} else { } else {
$finish["result"] = $dispatcher->store; $finish['result'] = $dispatcher->store;
$finish["retcode"] = 0; $finish['retcode'] = 0;
} }
if (zm_atomic("server_is_stopped")->get() === 1) { if (zm_atomic('server_is_stopped')->get() === 1) {
return; return;
} }
$task->finish($finish); $task->finish($finish);
@@ -59,17 +56,17 @@ class OnTask implements SwooleEvent
try { try {
$dispatcher = new EventDispatcher(OnTaskEvent::class); $dispatcher = new EventDispatcher(OnTaskEvent::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
/** @var OnTaskEvent $v */ /* @var OnTaskEvent $v */
return eval("return " . $v->getRule() . ";"); return eval('return ' . $v->getRule() . ';');
}); });
$dispatcher->dispatchEvents(); $dispatcher->dispatchEvents();
} catch (Exception $e) { } catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00026") . "Uncaught exception " . get_class($e) . " when calling \"task\": " . $error_msg); Console::error(zm_internal_errcode('E00026') . 'Uncaught exception ' . get_class($e) . ' when calling "task": ' . $error_msg);
Console::trace(); Console::trace();
} catch (Error $e) { } catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")"; $error_msg = $e->getMessage() . ' at ' . $e->getFile() . '(' . $e->getLine() . ')';
Console::error(zm_internal_errcode("E00026") . "Uncaught " . get_class($e) . " when calling \"task\": " . $error_msg); Console::error(zm_internal_errcode('E00026') . 'Uncaught ' . get_class($e) . ' when calling "task": ' . $error_msg);
Console::trace(); Console::trace();
} }
} }

View File

@@ -1,9 +1,11 @@
<?php /** @noinspection PhpUnusedParameterInspection */ <?php
/** @noinspection PhpUnusedParameterInspection */
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
use Swoole\Coroutine; use Swoole\Coroutine;
use Swoole\Server; use Swoole\Server;
use Swoole\Timer; use Swoole\Timer;
@@ -14,18 +16,18 @@ use ZM\Store\LightCacheInside;
/** /**
* Class OnWorkerExit * Class OnWorkerExit
* @package ZM\Event\SwooleEvent
* @SwooleHandler("WorkerExit") * @SwooleHandler("WorkerExit")
*/ */
class OnWorkerExit implements SwooleEvent class OnWorkerExit implements SwooleEvent
{ {
public function onCall(Server $server, $worker_id) { public function onCall(Server $server, $worker_id)
{
Timer::clearAll(); Timer::clearAll();
foreach((LightCacheInside::get("wait_api", "wait_api") ?? []) as $v) { foreach ((LightCacheInside::get('wait_api', 'wait_api') ?? []) as $v) {
if (($v["worker_id"] ?? -1) == $worker_id && isset($v["coroutine"])) { if (($v['worker_id'] ?? -1) == $worker_id && isset($v['coroutine'])) {
Coroutine::resume($v["coroutine"]); Coroutine::resume($v['coroutine']);
} }
} }
Console::info("正在结束 Worker #".$worker_id.",进程内可能有事务在运行..."); Console::info('正在结束 Worker #' . $worker_id . ',进程内可能有事务在运行...');
} }
} }

View File

@@ -1,5 +1,8 @@
<?php /** @noinspection PhpComposerExtensionStubsInspection */ <?php
/** @noinspection PhpComposerExtensionStubsInspection */
declare(strict_types=1);
namespace ZM\Event\SwooleEvent; namespace ZM\Event\SwooleEvent;
@@ -14,7 +17,6 @@ use Swoole\Server;
use ZM\Annotation\AnnotationParser; use ZM\Annotation\AnnotationParser;
use ZM\Annotation\Swoole\OnMessageEvent; use ZM\Annotation\Swoole\OnMessageEvent;
use ZM\Annotation\Swoole\OnStart; use ZM\Annotation\Swoole\OnStart;
use ZM\Annotation\Swoole\OnSwooleEvent;
use ZM\Annotation\Swoole\SwooleHandler; use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\Console\Console; use ZM\Console\Console;
@@ -38,37 +40,39 @@ use ZM\Utils\SignalListener;
/** /**
* Class OnWorkerStart * Class OnWorkerStart
* @package ZM\Event\SwooleEvent
* @SwooleHandler("WorkerStart") * @SwooleHandler("WorkerStart")
*/ */
class OnWorkerStart implements SwooleEvent class OnWorkerStart implements SwooleEvent
{ {
public function onCall(Server $server, $worker_id) public function onCall(Server $server, $worker_id)
{ {
Console::debug("Calling onWorkerStart event(1)"); Console::debug('Calling onWorkerStart event(1)');
if (!Framework::$argv["disable-safe-exit"]) { if (!Framework::$argv['disable-safe-exit']) {
SignalListener::signalWorker($server, $worker_id); SignalListener::signalWorker($server, $worker_id);
} }
unset(Context::$context[Coroutine::getCid()]); unset(Context::$context[Coroutine::getCid()]);
if ($server->taskworker === false) { if ($server->taskworker === false) {
Framework::saveProcessState(ZM_PROCESS_WORKER, $server->worker_pid, ['worker_id' => $worker_id]); Framework::saveProcessState(ZM_PROCESS_WORKER, $server->worker_pid, ['worker_id' => $worker_id]);
zm_atomic("_#worker_" . $worker_id)->set($server->worker_pid); zm_atomic('_#worker_' . $worker_id)->set($server->worker_pid);
if (LightCacheInside::get("wait_api", "wait_api") !== null) { if (LightCacheInside::get('wait_api', 'wait_api') !== null) {
LightCacheInside::unset("wait_api", "wait_api"); LightCacheInside::unset('wait_api', 'wait_api');
} }
try { try {
register_shutdown_function(function () use ($server) { register_shutdown_function(function () use ($server) {
$error = error_get_last(); $error = error_get_last();
if (($error["type"] ?? 0) != 0) { if (($error['type'] ?? 0) != 0) {
Console::error(zm_internal_errcode("E00027") . "Internal fatal error: " . $error["message"] . " at " . $error["file"] . "({$error["line"]})"); Console::error(zm_internal_errcode('E00027') . 'Internal fatal error: ' . $error['message'] . ' at ' . $error['file'] . "({$error['line']})");
zm_dump($error); zm_dump($error);
} elseif (!isset($error["type"])) { } elseif (!isset($error['type'])) {
return; return;
} }
//DataProvider::saveBuffer(); //DataProvider::saveBuffer();
/** @var Server $server */ /* @var Server $server */
if (server() === null) $server->shutdown(); if (server() === null) {
else server()->shutdown(); $server->shutdown();
} else {
server()->shutdown();
}
}); });
Console::verbose("Worker #{$server->worker_id} starting"); Console::verbose("Worker #{$server->worker_id} starting");
@@ -80,34 +84,40 @@ class OnWorkerStart implements SwooleEvent
$this->initMySQLPool(); $this->initMySQLPool();
// 开箱即用的Redis // 开箱即用的Redis
$redis = ZMConfig::get("global", "redis_config"); $redis = ZMConfig::get('global', 'redis_config');
if ($redis !== null && $redis["host"] != "") { if ($redis !== null && $redis['host'] != '') {
if (!extension_loaded("redis")) Console::error(zm_internal_errcode("E00029") . "Can not find redis extension.\n"); if (!extension_loaded('redis')) {
else ZMRedisPool::init($redis); Console::error(zm_internal_errcode('E00029') . "Can not find redis extension.\n");
} else {
ZMRedisPool::init($redis);
}
} }
$this->loadAnnotations(); //加载composer资源、phar外置包、注解解析注册等 $this->loadAnnotations(); //加载composer资源、phar外置包、注解解析注册等
EventManager::registerTimerTick(); //启动计时器 EventManager::registerTimerTick(); //启动计时器
set_coroutine_params(["server" => $server, "worker_id" => $worker_id]); set_coroutine_params(['server' => $server, 'worker_id' => $worker_id]);
$dispatcher = new EventDispatcher(OnStart::class); $dispatcher = new EventDispatcher(OnStart::class);
$dispatcher->setRuleFunction(function ($v) { $dispatcher->setRuleFunction(function ($v) {
return server()->worker_id === $v->worker_id || $v->worker_id === -1; return server()->worker_id === $v->worker_id || $v->worker_id === -1;
}); });
$dispatcher->dispatchEvents($server, $worker_id); $dispatcher->dispatchEvents($server, $worker_id);
if ($dispatcher->status === EventDispatcher::STATUS_NORMAL) Console::debug("@OnStart 执行完毕"); if ($dispatcher->status === EventDispatcher::STATUS_NORMAL) {
else Console::warning("@OnStart 执行异常!"); Console::debug('@OnStart 执行完毕');
Console::success("Worker #" . $worker_id . " started"); } else {
Console::warning('@OnStart 执行异常!');
}
Console::success('Worker #' . $worker_id . ' started');
} catch (Exception $e) { } catch (Exception $e) {
Console::error("Worker加载出错停止服务"); Console::error('Worker加载出错停止服务');
Console::error(zm_internal_errcode("E00030") . $e->getMessage() . "\n" . $e->getTraceAsString()); Console::error(zm_internal_errcode('E00030') . $e->getMessage() . "\n" . $e->getTraceAsString());
Process::kill($server->master_pid, SIGTERM); Process::kill($server->master_pid, SIGTERM);
return; return;
} catch (Error $e) { } catch (Error $e) {
Console::error(zm_internal_errcode("E00030") . "PHP Error: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine()); Console::error(zm_internal_errcode('E00030') . 'PHP Error: ' . $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine());
Console::error("Maybe it caused by your own code if in your own Module directory."); Console::error('Maybe it caused by your own code if in your own Module directory.');
Console::log($e->getTraceAsString(), 'gray'); Console::log($e->getTraceAsString(), 'gray');
if (!Framework::$argv["watch"]) { // 在热更新模式下不能退出 if (!Framework::$argv['watch']) { // 在热更新模式下不能退出
Process::kill($server->master_pid, SIGTERM); Process::kill($server->master_pid, SIGTERM);
} }
} }
@@ -117,15 +127,15 @@ class OnWorkerStart implements SwooleEvent
try { try {
Framework::$server = $server; Framework::$server = $server;
$this->loadAnnotations(); $this->loadAnnotations();
Console::success("TaskWorker #" . $server->worker_id . " started"); Console::success('TaskWorker #' . $server->worker_id . ' started');
} catch (Exception $e) { } catch (Exception $e) {
Console::error("Worker加载出错停止服务"); Console::error('Worker加载出错停止服务');
Console::error(zm_internal_errcode("E00030") . $e->getMessage() . "\n" . $e->getTraceAsString()); Console::error(zm_internal_errcode('E00030') . $e->getMessage() . "\n" . $e->getTraceAsString());
Process::kill($server->master_pid, SIGTERM); Process::kill($server->master_pid, SIGTERM);
return; return;
} catch (Error $e) { } catch (Error $e) {
Console::error(zm_internal_errcode("E00030") . "PHP Error: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine()); Console::error(zm_internal_errcode('E00030') . 'PHP Error: ' . $e->getMessage() . ' in ' . $e->getFile() . ' on line ' . $e->getLine());
Console::error("Maybe it caused by your own code if in your own Module directory."); Console::error('Maybe it caused by your own code if in your own Module directory.');
Console::log($e->getTraceAsString(), 'gray'); Console::log($e->getTraceAsString(), 'gray');
Process::kill($server->master_pid, SIGTERM); Process::kill($server->master_pid, SIGTERM);
} }
@@ -138,31 +148,41 @@ class OnWorkerStart implements SwooleEvent
*/ */
private function loadAnnotations() private function loadAnnotations()
{ {
if (Framework::$instant_mode) goto skip; if (Framework::$instant_mode) {
goto skip;
}
//加载各个模块的注解类,以及反射 //加载各个模块的注解类,以及反射
Console::debug("Mapping annotations"); Console::debug('Mapping annotations');
$parser = new AnnotationParser(); $parser = new AnnotationParser();
$composer = json_decode(file_get_contents(DataProvider::getSourceRootDir() . "/composer.json"), true); $composer = json_decode(file_get_contents(DataProvider::getSourceRootDir() . '/composer.json'), true);
$merge = array_merge($composer["autoload"]["psr-4"] ?? [], $composer["autoload-dev"]["psr-4"] ?? []); $merge = array_merge($composer['autoload']['psr-4'] ?? [], $composer['autoload-dev']['psr-4'] ?? []);
foreach ($merge as $k => $v) { foreach ($merge as $k => $v) {
if (is_dir(DataProvider::getSourceRootDir() . "/" . $v)) { if (is_dir(DataProvider::getSourceRootDir() . '/' . $v)) {
if (in_array(trim($k, "\\") . "\\", $composer["extra"]["exclude_annotate"] ?? [])) continue; if (in_array(trim($k, '\\') . '\\', $composer['extra']['exclude_annotate'] ?? [])) {
if (trim($k, "\\") == "ZM") continue; continue;
if (\server()->worker_id == 0) Console::verbose("Add " . $v . ":$k to register path"); }
$parser->addRegisterPath(DataProvider::getSourceRootDir() . "/" . $v . "/", trim($k, "\\")); if (trim($k, '\\') == 'ZM') {
continue;
}
if (\server()->worker_id == 0) {
Console::verbose('Add ' . $v . ":{$k} to register path");
}
$parser->addRegisterPath(DataProvider::getSourceRootDir() . '/' . $v . '/', trim($k, '\\'));
} }
} }
// 检查是否允许热加载phar模块允许的话将遍历phar内的文件 // 检查是否允许热加载phar模块允许的话将遍历phar内的文件
$plugin_enable_hotload = ZMConfig::get("global", "module_loader")["enable_hotload"] ?? false; $plugin_enable_hotload = ZMConfig::get('global', 'module_loader')['enable_hotload'] ?? false;
if ($plugin_enable_hotload) { if ($plugin_enable_hotload) {
$list = ModuleManager::getPackedModules(); $list = ModuleManager::getPackedModules();
foreach ($list as $k => $v) { foreach ($list as $k => $v) {
if (\server()->worker_id === 0) Console::info("Loading packed module: " . $k); if (\server()->worker_id === 0) {
require_once $v["phar-path"]; Console::info('Loading packed module: ' . $k);
$func = "loader" . $v["generated-id"]; }
require_once $v['phar-path'];
$func = 'loader' . $v['generated-id'];
$func(); $func();
$parser->addRegisterPath("phar://" . $v["phar-path"] . "/" . $v["module-root-path"], $v["namespace"]); $parser->addRegisterPath('phar://' . $v['phar-path'] . '/' . $v['module-root-path'], $v['namespace']);
} }
} }
@@ -171,27 +191,27 @@ class OnWorkerStart implements SwooleEvent
skip: skip:
//加载自定义的全局函数 //加载自定义的全局函数
Console::debug("Loading context class..."); Console::debug('Loading context class...');
$context_class = ZMConfig::get("global", "context_class"); $context_class = ZMConfig::get('global', 'context_class');
if (!is_a($context_class, ContextInterface::class, true)) { if (!is_a($context_class, ContextInterface::class, true)) {
throw new ZMKnownException("E00032", "Context class must implemented from ContextInterface!"); throw new ZMKnownException('E00032', 'Context class must implemented from ContextInterface!');
} }
//加载插件 //加载插件
$obb_onebot = ZMConfig::get("global", "onebot") ?? $obb_onebot = ZMConfig::get('global', 'onebot') ??
ZMConfig::get("global", "modules")["onebot"] ?? ZMConfig::get('global', 'modules')['onebot'] ??
["status" => true, "single_bot_mode" => false, "message_level" => 99999]; ['status' => true, 'single_bot_mode' => false, 'message_level' => 99999];
if ($obb_onebot["status"]) { if ($obb_onebot['status']) {
Console::debug("OneBot support enabled, listening OneBot event(3)."); Console::debug('OneBot support enabled, listening OneBot event(3).');
$obj = new OnMessageEvent(); $obj = new OnMessageEvent();
$obj->class = QQBot::class; $obj->class = QQBot::class;
$obj->method = 'handleByEvent'; $obj->method = 'handleByEvent';
$obj->level = $obb_onebot["message_level"] ?? 99; $obj->level = $obb_onebot['message_level'] ?? 99;
$obj->rule = 'connectIsQQ()'; $obj->rule = 'connectIsQQ()';
EventManager::addEvent(OnMessageEvent::class, $obj); EventManager::addEvent(OnMessageEvent::class, $obj);
if ($obb_onebot["single_bot_mode"]) { if ($obb_onebot['single_bot_mode']) {
LightCacheInside::set("connect", "conn_fd", -1); LightCacheInside::set('connect', 'conn_fd', -1);
} else { } else {
LightCacheInside::set("connect", "conn_fd", -2); LightCacheInside::set('connect', 'conn_fd', -2);
} }
} }
} }
@@ -203,56 +223,61 @@ class OnWorkerStart implements SwooleEvent
SqlPoolStorage::$sql_pool = null; SqlPoolStorage::$sql_pool = null;
} }
$real_conf = []; $real_conf = [];
if (isset(ZMConfig::get("global", "sql_config")["sql_host"])) { if (isset(ZMConfig::get('global', 'sql_config')['sql_host'])) {
if (ZMConfig::get("global", "sql_config")["sql_host"] != "") { if (ZMConfig::get('global', 'sql_config')['sql_host'] != '') {
if (\server()->worker_id === 0) { if (\server()->worker_id === 0) {
Console::warning("使用 'sql_config' 配置项和 DB 数据库查询构造器进行查询数据库可能会在下一个大版本中废弃,请使用 'mysql_config' 搭配 doctrine dbal 使用!"); Console::warning("使用 'sql_config' 配置项和 DB 数据库查询构造器进行查询数据库可能会在下一个大版本中废弃,请使用 'mysql_config' 搭配 doctrine dbal 使用!");
Console::warning("详见: `https://framework.zhamao.xin/`"); Console::warning('详见: `https://framework.zhamao.xin/`');
} }
$origin_conf = ZMConfig::get("global", "sql_config"); $origin_conf = ZMConfig::get('global', 'sql_config');
$real_conf = [ $real_conf = [
"host" => $origin_conf["sql_host"], 'host' => $origin_conf['sql_host'],
"port" => $origin_conf["sql_port"], 'port' => $origin_conf['sql_port'],
"username" => $origin_conf["sql_username"], 'username' => $origin_conf['sql_username'],
"password" => $origin_conf["sql_password"], 'password' => $origin_conf['sql_password'],
"dbname" => $origin_conf["sql_database"], 'dbname' => $origin_conf['sql_database'],
"options" => $origin_conf["sql_options"], 'options' => $origin_conf['sql_options'],
'unix_socket' => null, 'unix_socket' => null,
'charset' => 'utf8mb4', 'charset' => 'utf8mb4',
'pool_size' => 64 'pool_size' => 64,
]; ];
} }
} }
if (isset(ZMConfig::get("global", "mysql_config")["host"])) { if (isset(ZMConfig::get('global', 'mysql_config')['host'])) {
if (ZMConfig::get("global", "mysql_config")["host"] != "") { if (ZMConfig::get('global', 'mysql_config')['host'] != '') {
$real_conf = ZMConfig::get("global", "mysql_config"); $real_conf = ZMConfig::get('global', 'mysql_config');
} }
} }
if (!empty($real_conf)) { if (!empty($real_conf)) {
Console::info("Connecting to MySQL pool"); Console::info('Connecting to MySQL pool');
ob_start(); ob_start();
phpinfo(); //这个phpinfo是有用的不能删除 phpinfo(); //这个phpinfo是有用的不能删除
$str = ob_get_clean(); $str = ob_get_clean();
$str = explode("\n", $str); $str = explode("\n", $str);
foreach ($str as $v) { foreach ($str as $v) {
$v = trim($v); $v = trim($v);
if ($v == "") continue; if ($v == '') {
if (mb_strpos($v, "API Extensions") === false) continue; continue;
if (mb_strpos($v, "pdo_mysql") === false) { }
throw new DbException(zm_internal_errcode("E00028") . "未安装 mysqlnd php-mysql扩展。"); if (mb_strpos($v, 'API Extensions') === false) {
continue;
}
if (mb_strpos($v, 'pdo_mysql') === false) {
throw new DbException(zm_internal_errcode('E00028') . '未安装 mysqlnd php-mysql扩展。');
} }
} }
SqlPoolStorage::$sql_pool = new MySQLPool((new PDOConfig()) SqlPoolStorage::$sql_pool = new MySQLPool(
->withHost($real_conf["host"]) (new PDOConfig())
->withPort($real_conf["port"]) ->withHost($real_conf['host'])
->withPort($real_conf['port'])
// ->withUnixSocket('/tmp/mysql.sock') // ->withUnixSocket('/tmp/mysql.sock')
->withDbName($real_conf["dbname"]) ->withDbName($real_conf['dbname'])
->withCharset($real_conf["charset"]) ->withCharset($real_conf['charset'])
->withUsername($real_conf["username"]) ->withUsername($real_conf['username'])
->withPassword($real_conf["password"]) ->withPassword($real_conf['password'])
->withOptions($real_conf["options"] ?? [PDO::ATTR_STRINGIFY_FETCHES => false]) ->withOptions($real_conf['options'] ?? [PDO::ATTR_STRINGIFY_FETCHES => false])
); );
DB::initTableList($real_conf["dbname"]); DB::initTableList($real_conf['dbname']);
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More