mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-21 07:35:34 +08:00
add cs fixer and PHPStan and activate it (build 436)
This commit is contained in:
@@ -1,62 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Swoole\Coroutine;
|
||||
use ZM\Store\LightCacheInside;
|
||||
use ZM\Store\Lock\SpinLock;
|
||||
use ZM\Store\ZMAtomic;
|
||||
use ZM\Utils\Manager\ProcessManager;
|
||||
use ZM\Utils\Manager\WorkerManager;
|
||||
|
||||
class CoMessage
|
||||
{
|
||||
/**
|
||||
* @param array $hang
|
||||
* @param array $compare
|
||||
* @param int $timeout
|
||||
* @param int $timeout
|
||||
* @return mixed
|
||||
*/
|
||||
public static function yieldByWS(array $hang, array $compare, $timeout = 600) {
|
||||
public static function yieldByWS(array $hang, array $compare, $timeout = 600)
|
||||
{
|
||||
$cid = Coroutine::getuid();
|
||||
$api_id = ZMAtomic::get("wait_msg_id")->add(1);
|
||||
$hang["compare"] = $compare;
|
||||
$hang["coroutine"] = $cid;
|
||||
$hang["worker_id"] = server()->worker_id;
|
||||
$hang["result"] = null;
|
||||
SpinLock::lock("wait_api");
|
||||
$wait = LightCacheInside::get("wait_api", "wait_api");
|
||||
$api_id = ZMAtomic::get('wait_msg_id')->add(1);
|
||||
$hang['compare'] = $compare;
|
||||
$hang['coroutine'] = $cid;
|
||||
$hang['worker_id'] = server()->worker_id;
|
||||
$hang['result'] = null;
|
||||
SpinLock::lock('wait_api');
|
||||
$wait = LightCacheInside::get('wait_api', 'wait_api');
|
||||
$wait[$api_id] = $hang;
|
||||
LightCacheInside::set("wait_api", "wait_api", $wait);
|
||||
SpinLock::unlock("wait_api");
|
||||
LightCacheInside::set('wait_api', 'wait_api', $wait);
|
||||
SpinLock::unlock('wait_api');
|
||||
$id = swoole_timer_after($timeout * 1000, function () use ($api_id) {
|
||||
$r = LightCacheInside::get("wait_api", "wait_api")[$api_id] ?? null;
|
||||
$r = LightCacheInside::get('wait_api', 'wait_api')[$api_id] ?? null;
|
||||
if (is_array($r)) {
|
||||
Coroutine::resume($r["coroutine"]);
|
||||
Coroutine::resume($r['coroutine']);
|
||||
}
|
||||
});
|
||||
Coroutine::suspend();
|
||||
SpinLock::lock("wait_api");
|
||||
$sess = LightCacheInside::get("wait_api", "wait_api");
|
||||
$result = $sess[$api_id]["result"] ?? null;
|
||||
SpinLock::lock('wait_api');
|
||||
$sess = LightCacheInside::get('wait_api', 'wait_api');
|
||||
$result = $sess[$api_id]['result'] ?? null;
|
||||
unset($sess[$api_id]);
|
||||
LightCacheInside::set("wait_api", "wait_api", $sess);
|
||||
SpinLock::unlock("wait_api");
|
||||
if (isset($id)) swoole_timer_clear($id);
|
||||
if ($result === null) return false;
|
||||
LightCacheInside::set('wait_api', 'wait_api', $sess);
|
||||
SpinLock::unlock('wait_api');
|
||||
if (isset($id)) {
|
||||
swoole_timer_clear($id);
|
||||
}
|
||||
if ($result === null) {
|
||||
return false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function resumeByWS(): bool {
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function resumeByWS(): bool
|
||||
{
|
||||
$dat = ctx()->getData();
|
||||
$last = null;
|
||||
SpinLock::lock("wait_api");
|
||||
$all = LightCacheInside::get("wait_api", "wait_api") ?? [];
|
||||
SpinLock::lock('wait_api');
|
||||
$all = LightCacheInside::get('wait_api', 'wait_api') ?? [];
|
||||
foreach ($all as $k => $v) {
|
||||
if (!isset($v["compare"])) continue;
|
||||
foreach ($v["compare"] as $vs) {
|
||||
if (!isset($v[$vs], $dat[$vs])) continue 2;
|
||||
if (!isset($v['compare'])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($v['compare'] as $vs) {
|
||||
if (!isset($v[$vs], $dat[$vs])) {
|
||||
continue 2;
|
||||
}
|
||||
if ($v[$vs] != $dat[$vs]) {
|
||||
continue 2;
|
||||
}
|
||||
@@ -64,18 +76,17 @@ class CoMessage
|
||||
$last = $k;
|
||||
}
|
||||
if ($last !== null) {
|
||||
$all[$last]["result"] = $dat;
|
||||
LightCacheInside::set("wait_api", "wait_api", $all);
|
||||
SpinLock::unlock("wait_api");
|
||||
if ($all[$last]["worker_id"] != server()->worker_id) {
|
||||
ProcessManager::sendActionToWorker($all[$last]["worker_id"], "resume_ws_message", $all[$last]);
|
||||
$all[$last]['result'] = $dat;
|
||||
LightCacheInside::set('wait_api', 'wait_api', $all);
|
||||
SpinLock::unlock('wait_api');
|
||||
if ($all[$last]['worker_id'] != server()->worker_id) {
|
||||
WorkerManager::sendActionToWorker($all[$last]['worker_id'], 'resume_ws_message', $all[$last]);
|
||||
} else {
|
||||
Coroutine::resume($all[$last]["coroutine"]);
|
||||
Coroutine::resume($all[$last]['coroutine']);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
SpinLock::unlock("wait_api");
|
||||
return false;
|
||||
}
|
||||
SpinLock::unlock('wait_api');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Swoole\Coroutine;
|
||||
|
||||
class CoroutinePool
|
||||
@@ -16,8 +16,11 @@ class CoroutinePool
|
||||
|
||||
private static $yields = [];
|
||||
|
||||
public static function go(callable $func, $name = "default") {
|
||||
if (!isset(self::$cids[$name])) self::$cids[$name] = [];
|
||||
public static function go(callable $func, $name = 'default')
|
||||
{
|
||||
if (!isset(self::$cids[$name])) {
|
||||
self::$cids[$name] = [];
|
||||
}
|
||||
if (count(self::$cids[$name]) >= (self::$sizes[$name] ?? self::$default_size)) {
|
||||
self::$yields[] = Coroutine::getCid();
|
||||
Coroutine::suspend();
|
||||
@@ -30,19 +33,23 @@ class CoroutinePool
|
||||
});
|
||||
}
|
||||
|
||||
public static function defaultSize(int $size) {
|
||||
public static function defaultSize(int $size)
|
||||
{
|
||||
self::$default_size = $size;
|
||||
}
|
||||
|
||||
public static function setSize($name, int $size) {
|
||||
public static function setSize($name, int $size)
|
||||
{
|
||||
self::$sizes[$name] = $size;
|
||||
}
|
||||
|
||||
public static function getRunningCoroutineCount($name = "default") {
|
||||
public static function getRunningCoroutineCount($name = 'default')
|
||||
{
|
||||
return count(self::$cids[$name]);
|
||||
}
|
||||
|
||||
private static function checkCids($name) {
|
||||
private static function checkCids($name)
|
||||
{
|
||||
if (in_array(Coroutine::getCid(), self::$cids[$name])) {
|
||||
$a = array_search(Coroutine::getCid(), self::$cids[$name]);
|
||||
array_splice(self::$cids[$name], $a, 1);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Console\Console;
|
||||
|
||||
@@ -13,9 +14,9 @@ class DataProvider
|
||||
|
||||
/**
|
||||
* 返回资源目录
|
||||
* @return string
|
||||
*/
|
||||
public static function getResourceFolder(): string {
|
||||
public static function getResourceFolder(): string
|
||||
{
|
||||
return self::getWorkingDir() . '/resources/';
|
||||
}
|
||||
|
||||
@@ -23,7 +24,8 @@ class DataProvider
|
||||
* 返回工作目录,不带最右边文件夹的斜杠(/)
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getWorkingDir() {
|
||||
public static function getWorkingDir()
|
||||
{
|
||||
return WORKING_DIR;
|
||||
}
|
||||
|
||||
@@ -31,7 +33,8 @@ class DataProvider
|
||||
* 获取框架所在根目录
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getFrameworkRootDir() {
|
||||
public static function getFrameworkRootDir()
|
||||
{
|
||||
return FRAMEWORK_ROOT_DIR;
|
||||
}
|
||||
|
||||
@@ -39,28 +42,32 @@ class DataProvider
|
||||
* 获取源码根目录,除Phar模式外均与工作目录相同
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getSourceRootDir() {
|
||||
return defined("SOURCE_ROOT_DIR") ? SOURCE_ROOT_DIR : WORKING_DIR;
|
||||
public static function getSourceRootDir()
|
||||
{
|
||||
return defined('SOURCE_ROOT_DIR') ? SOURCE_ROOT_DIR : WORKING_DIR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取框架反代链接
|
||||
* @return array|false|mixed|null
|
||||
* @return null|array|false|mixed
|
||||
*/
|
||||
public static function getFrameworkLink() {
|
||||
return ZMConfig::get("global", "http_reverse_link");
|
||||
public static function getFrameworkLink()
|
||||
{
|
||||
return ZMConfig::get('global', 'http_reverse_link');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取zm_data数据目录,如果二级目录不为空,则自动创建目录并返回
|
||||
* @param string $second
|
||||
* @return array|false|mixed|string|null
|
||||
* @return null|array|false|mixed|string
|
||||
*/
|
||||
public static function getDataFolder(string $second = '') {
|
||||
public static function getDataFolder(string $second = '')
|
||||
{
|
||||
if ($second !== '') {
|
||||
@mkdir(ZM_DATA . $second);
|
||||
if (!is_dir(ZM_DATA . $second)) return false;
|
||||
return realpath(ZM_DATA . $second) . "/";
|
||||
if (!is_dir(ZM_DATA . $second)) {
|
||||
return false;
|
||||
}
|
||||
return realpath(ZM_DATA . $second) . '/';
|
||||
}
|
||||
return ZM_DATA;
|
||||
}
|
||||
@@ -71,65 +78,74 @@ class DataProvider
|
||||
* @param $file_array
|
||||
* @return false|int
|
||||
*/
|
||||
public static function saveToJson($filename, $file_array) {
|
||||
$path = ZMConfig::get("global", "config_dir");
|
||||
$r = explode("/", $filename);
|
||||
public static function saveToJson($filename, $file_array)
|
||||
{
|
||||
$path = ZMConfig::get('global', 'config_dir');
|
||||
$r = explode('/', $filename);
|
||||
if (count($r) == 2) {
|
||||
$path = $path . $r[0] . "/";
|
||||
if (!is_dir($path)) mkdir($path);
|
||||
$path = $path . $r[0] . '/';
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
$name = $r[1];
|
||||
} elseif (count($r) != 1) {
|
||||
Console::warning(zm_internal_errcode("E00057") . "存储失败,文件名只能有一级目录");
|
||||
Console::warning(zm_internal_errcode('E00057') . '存储失败,文件名只能有一级目录');
|
||||
return false;
|
||||
} else {
|
||||
$name = $r[0];
|
||||
}
|
||||
return file_put_contents($path . $name . ".json", json_encode($file_array, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
return file_put_contents($path . $name . '.json', json_encode($file_array, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从json加载变量到内存
|
||||
* @param $filename
|
||||
* @return mixed|null
|
||||
* @return null|mixed
|
||||
*/
|
||||
public static function loadFromJson($filename) {
|
||||
$path = ZMConfig::get("global", "config_dir");
|
||||
if (file_exists($path . $filename . ".json")) {
|
||||
return json_decode(file_get_contents($path . $filename . ".json"), true);
|
||||
} else {
|
||||
return null;
|
||||
public static function loadFromJson($filename)
|
||||
{
|
||||
$path = ZMConfig::get('global', 'config_dir');
|
||||
if (file_exists($path . $filename . '.json')) {
|
||||
return json_decode(file_get_contents($path . $filename . '.json'), true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归或非递归扫描目录,可返回相对目录的文件列表或绝对目录的文件列表
|
||||
* @param $dir
|
||||
* @param bool $recursive
|
||||
* @param bool|string $relative
|
||||
* @param bool|string $relative
|
||||
* @return array|false
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function scanDirFiles($dir, bool $recursive = true, $relative = false) {
|
||||
$dir = rtrim($dir, "/");
|
||||
if (!is_dir($dir)) return false;
|
||||
public static function scanDirFiles($dir, bool $recursive = true, $relative = false)
|
||||
{
|
||||
$dir = rtrim($dir, '/');
|
||||
if (!is_dir($dir)) {
|
||||
return false;
|
||||
}
|
||||
$r = scandir($dir);
|
||||
if ($r === false) return false;
|
||||
if ($r === false) {
|
||||
return false;
|
||||
}
|
||||
$list = [];
|
||||
if ($relative === true) {
|
||||
$relative = $dir;
|
||||
}
|
||||
foreach ($r as $v) {
|
||||
if ($v == "." || $v == "..") continue;
|
||||
$sub_file = $dir . "/" . $v;
|
||||
if ($v == '.' || $v == '..') {
|
||||
continue;
|
||||
}
|
||||
$sub_file = $dir . '/' . $v;
|
||||
if (is_dir($sub_file) && $recursive) {
|
||||
$list = array_merge($list, self::scanDirFiles($sub_file, $recursive, $relative));
|
||||
} elseif (is_file($sub_file)) {
|
||||
if (is_string($relative) && mb_strpos($sub_file, $relative) === 0) {
|
||||
$list [] = ltrim(mb_substr($sub_file, mb_strlen($relative)), "/");
|
||||
$list[] = ltrim(mb_substr($sub_file, mb_strlen($relative)), '/');
|
||||
} elseif ($relative === false) {
|
||||
$list[] = $sub_file;
|
||||
} else {
|
||||
Console::warning(zm_internal_errcode("E00058") . "Relative path is not generated: wrong base directory ($relative)");
|
||||
Console::warning(zm_internal_errcode('E00058') . "Relative path is not generated: wrong base directory ({$relative})");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +159,8 @@ class DataProvider
|
||||
* @return bool
|
||||
* @since 2.5
|
||||
*/
|
||||
public static function isRelativePath($path) {
|
||||
public static function isRelativePath($path)
|
||||
{
|
||||
return strlen($path) > 0 && $path[0] === '/';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php /** @noinspection PhpMissingReturnTypeInspection */
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Swoole\Coroutine;
|
||||
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
|
||||
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
|
||||
@@ -18,7 +18,8 @@ use ZM\Utils\Manager\RouteManager;
|
||||
class HttpUtil
|
||||
{
|
||||
/** @noinspection PhpMissingReturnTypeInspection */
|
||||
public static function parseUri($request, $response, $uri, &$node, &$params) {
|
||||
public static function parseUri($request, $response, $uri, &$node, &$params)
|
||||
{
|
||||
$context = new RequestContext();
|
||||
$context->setMethod($request->server['request_method']);
|
||||
|
||||
@@ -26,8 +27,8 @@ class HttpUtil
|
||||
$matcher = new UrlMatcher(RouteManager::$routes ?? new RouteCollection(), $context);
|
||||
$matched = $matcher->match($uri);
|
||||
} catch (ResourceNotFoundException $e) {
|
||||
if (ZMConfig::get("global", "static_file_server")["status"]) {
|
||||
HttpUtil::handleStaticPage($request->server["request_uri"], $response);
|
||||
if (ZMConfig::get('global', 'static_file_server')['status']) {
|
||||
HttpUtil::handleStaticPage($request->server['request_uri'], $response);
|
||||
return null;
|
||||
}
|
||||
$matched = null;
|
||||
@@ -36,72 +37,76 @@ class HttpUtil
|
||||
}
|
||||
if ($matched !== null) {
|
||||
$node = [
|
||||
"route" => RouteManager::$routes->get($matched["_route"])->getPath(),
|
||||
"class" => $matched["_class"],
|
||||
"method" => $matched["_method"],
|
||||
"request_method" => $request->server['request_method']
|
||||
'route' => RouteManager::$routes->get($matched['_route'])->getPath(),
|
||||
'class' => $matched['_class'],
|
||||
'method' => $matched['_method'],
|
||||
'request_method' => $request->server['request_method'],
|
||||
];
|
||||
unset($matched["_class"], $matched["_method"]);
|
||||
unset($matched['_class'], $matched['_method']);
|
||||
$params = $matched;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getHttpCodePage(int $http_code) {
|
||||
if (isset(ZMConfig::get("global", "http_default_code_page")[$http_code])) {
|
||||
return Coroutine::readFile(DataProvider::getResourceFolder() . "html/" . ZMConfig::get("global", "http_default_code_page")[$http_code]);
|
||||
} else return null;
|
||||
public static function getHttpCodePage(int $http_code)
|
||||
{
|
||||
if (isset(ZMConfig::get('global', 'http_default_code_page')[$http_code])) {
|
||||
return Coroutine::readFile(DataProvider::getResourceFolder() . 'html/' . ZMConfig::get('global', 'http_default_code_page')[$http_code]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $uri
|
||||
* @param Response|\Swoole\Http\Response $response
|
||||
* @param array $settings
|
||||
* @param Response|\Swoole\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
public static function handleStaticPage($uri, $response, $settings = []) {
|
||||
$base_dir = $settings["document_root"] ?? ZMConfig::get("global", "static_file_server")["document_root"];
|
||||
$base_index = $settings["document_index"] ?? ZMConfig::get("global", "static_file_server")["document_index"];
|
||||
public static function handleStaticPage($uri, $response, array $settings = [])
|
||||
{
|
||||
$base_dir = $settings['document_root'] ?? ZMConfig::get('global', 'static_file_server')['document_root'];
|
||||
$base_index = $settings['document_index'] ?? ZMConfig::get('global', 'static_file_server')['document_index'];
|
||||
$path = realpath($base_dir . urldecode($uri));
|
||||
if ($path !== false) {
|
||||
if (is_dir($path)) $path = $path . '/';
|
||||
if (is_dir($path)) {
|
||||
$path = $path . '/';
|
||||
}
|
||||
$work = realpath($base_dir) . '/';
|
||||
if (strpos($path, $work) !== 0) {
|
||||
Console::info("[403] " . $uri);
|
||||
Console::info('[403] ' . $uri);
|
||||
self::responseCodePage($response, 403);
|
||||
return true;
|
||||
}
|
||||
if (is_dir($path)) {
|
||||
if (mb_substr($uri, -1, 1) != "/") {
|
||||
Console::info("[302] " . $uri);
|
||||
$response->redirect($uri . "/", 302);
|
||||
if (mb_substr($uri, -1, 1) != '/') {
|
||||
Console::info('[302] ' . $uri);
|
||||
$response->redirect($uri . '/', 302);
|
||||
return true;
|
||||
}
|
||||
foreach ($base_index as $vp) {
|
||||
if (is_file($path . "/" . $vp)) {
|
||||
Console::info("[200] " . $uri);
|
||||
$exp = strtolower(pathinfo($path . $vp)['extension'] ?? "unknown");
|
||||
$response->setHeader("Content-Type", ZMConfig::get("file_header")[$exp] ?? "application/octet-stream");
|
||||
if (is_file($path . '/' . $vp)) {
|
||||
Console::info('[200] ' . $uri);
|
||||
$exp = strtolower(pathinfo($path . $vp)['extension'] ?? 'unknown');
|
||||
$response->setHeader('Content-Type', ZMConfig::get('file_header')[$exp] ?? 'application/octet-stream');
|
||||
$response->end(file_get_contents($path . $vp));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif (is_file($path)) {
|
||||
Console::info("[200] " . $uri);
|
||||
$exp = strtolower(pathinfo($path)['extension'] ?? "unknown");
|
||||
$response->setHeader("Content-Type", ZMConfig::get("file_header")[$exp] ?? "application/octet-stream");
|
||||
Console::info('[200] ' . $uri);
|
||||
$exp = strtolower(pathinfo($path)['extension'] ?? 'unknown');
|
||||
$response->setHeader('Content-Type', ZMConfig::get('file_header')[$exp] ?? 'application/octet-stream');
|
||||
$response->end(file_get_contents($path));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Console::info("[404] " . $uri);
|
||||
Console::info('[404] ' . $uri);
|
||||
self::responseCodePage($response, 404);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function responseCodePage($response, $code) {
|
||||
public static function responseCodePage($response, $code)
|
||||
{
|
||||
$response->status($code);
|
||||
$response->end(self::getHttpCodePage($code));
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Console\Console;
|
||||
use ZM\Exception\ModulePackException;
|
||||
@@ -16,67 +16,80 @@ use ZM\Utils\DataProvider;
|
||||
/**
|
||||
* 模块管理器,负责打包解包模块
|
||||
* Class ModuleManager
|
||||
* @package ZM\Utils\Manager
|
||||
* @since 2.5
|
||||
*/
|
||||
class ModuleManager
|
||||
{
|
||||
|
||||
/**
|
||||
* 扫描src目录下的所有已经被标注的模块
|
||||
* @return array
|
||||
* @throws ZMException
|
||||
*/
|
||||
public static function getConfiguredModules(): array {
|
||||
$dir = DataProvider::getSourceRootDir() . "/src/";
|
||||
public static function getConfiguredModules(): array
|
||||
{
|
||||
$dir = DataProvider::getSourceRootDir() . '/src/';
|
||||
$ls = DataProvider::scanDirFiles($dir, true, true);
|
||||
$modules = [];
|
||||
foreach ($ls as $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if ($pathinfo["basename"] == "zm.json") {
|
||||
$json = json_decode(file_get_contents(realpath($dir . "/" . $v)), true);
|
||||
if ($json === null) continue;
|
||||
if (!isset($json["name"])) continue;
|
||||
if ($pathinfo["dirname"] == ".") {
|
||||
throw new ZMKnownException("E00052", "在/src/目录下不可以直接标记为模块(zm.json),因为命名空间不能为根空间!");
|
||||
if ($pathinfo['basename'] == 'zm.json') {
|
||||
$json = json_decode(file_get_contents(realpath($dir . '/' . $v)), true);
|
||||
if ($json === null) {
|
||||
continue;
|
||||
}
|
||||
$json["module-path"] = realpath($dir . "/" . $pathinfo["dirname"]);
|
||||
$json["namespace"] = str_replace("/", "\\", $pathinfo["dirname"]);
|
||||
if (isset($modules[$json["name"]])) {
|
||||
throw new ZMKnownException("E00053", "重名模块:" . $json["name"]);
|
||||
if (!isset($json['name'])) {
|
||||
continue;
|
||||
}
|
||||
$modules[$json["name"]] = $json;
|
||||
if ($pathinfo['dirname'] == '.') {
|
||||
throw new ZMKnownException('E00052', '在/src/目录下不可以直接标记为模块(zm.json),因为命名空间不能为根空间!');
|
||||
}
|
||||
$json['module-path'] = realpath($dir . '/' . $pathinfo['dirname']);
|
||||
$json['namespace'] = str_replace('/', '\\', $pathinfo['dirname']);
|
||||
if (isset($modules[$json['name']])) {
|
||||
throw new ZMKnownException('E00053', '重名模块:' . $json['name']);
|
||||
}
|
||||
$modules[$json['name']] = $json;
|
||||
}
|
||||
}
|
||||
return $modules;
|
||||
}
|
||||
|
||||
public static function getPackedModules(): array {
|
||||
$dir = ZMConfig::get("global", "module_loader")["load_path"] ?? (ZM_DATA . "modules");
|
||||
public static function getPackedModules(): array
|
||||
{
|
||||
$dir = ZMConfig::get('global', 'module_loader')['load_path'] ?? (ZM_DATA . 'modules');
|
||||
$ls = DataProvider::scanDirFiles($dir, true, false);
|
||||
if ($ls === false) return [];
|
||||
if ($ls === false) {
|
||||
return [];
|
||||
}
|
||||
$modules = [];
|
||||
foreach ($ls as $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if (($pathinfo["extension"] ?? "") != "phar") continue;
|
||||
$file = "phar://" . $v;
|
||||
if (!is_file($file . "/module_entry.php") || !is_file($file . "/zmplugin.json")) continue;
|
||||
$module_config = json_decode(file_get_contents($file . "/zmplugin.json"), true);
|
||||
if ($module_config === null) continue;
|
||||
if (!is_file($file . "/" . $module_config["module-root-path"] . "/zm.json")) {
|
||||
Console::warning(zm_internal_errcode("E00054") . "模块(插件)文件 " . $pathinfo["basename"] . " 无法找到模块配置文件(zm.json)!");
|
||||
if (($pathinfo['extension'] ?? '') != 'phar') {
|
||||
continue;
|
||||
}
|
||||
$module_file = json_decode(file_get_contents($file . "/" . $module_config["module-root-path"] . "/zm.json"), true);
|
||||
$file = 'phar://' . $v;
|
||||
if (!is_file($file . '/module_entry.php') || !is_file($file . '/zmplugin.json')) {
|
||||
continue;
|
||||
}
|
||||
$module_config = json_decode(file_get_contents($file . '/zmplugin.json'), true);
|
||||
if ($module_config === null) {
|
||||
continue;
|
||||
}
|
||||
if (!is_file($file . '/' . $module_config['module-root-path'] . '/zm.json')) {
|
||||
Console::warning(zm_internal_errcode('E00054') . '模块(插件)文件 ' . $pathinfo['basename'] . ' 无法找到模块配置文件(zm.json)!');
|
||||
continue;
|
||||
}
|
||||
$module_file = json_decode(file_get_contents($file . '/' . $module_config['module-root-path'] . '/zm.json'), true);
|
||||
if ($module_file === null) {
|
||||
Console::warning(zm_internal_errcode("E000555") . "模块(插件)文件 " . $pathinfo["basename"] . " 无法正常读取模块配置文件(zm.json)!");
|
||||
Console::warning(zm_internal_errcode('E000555') . '模块(插件)文件 ' . $pathinfo['basename'] . ' 无法正常读取模块配置文件(zm.json)!');
|
||||
continue;
|
||||
}
|
||||
$module_config["phar-path"] = $v;
|
||||
$module_config["name"] = $module_file["name"] ?? null;
|
||||
if ($module_config["name"] === null) continue;
|
||||
$module_config["module-config"] = $module_file;
|
||||
$modules[$module_config["name"]] = $module_config;
|
||||
$module_config['phar-path'] = $v;
|
||||
$module_config['name'] = $module_file['name'] ?? null;
|
||||
if ($module_config['name'] === null) {
|
||||
continue;
|
||||
}
|
||||
$module_config['module-config'] = $module_file;
|
||||
$modules[$module_config['name']] = $module_config;
|
||||
}
|
||||
return $modules;
|
||||
}
|
||||
@@ -84,15 +97,19 @@ class ModuleManager
|
||||
/**
|
||||
* 打包模块
|
||||
* @param $module
|
||||
* @return bool
|
||||
* @throws ZMException
|
||||
*/
|
||||
public static function packModule($module): bool {
|
||||
public static function packModule($module): bool
|
||||
{
|
||||
try {
|
||||
$packer = new ModulePacker($module);
|
||||
if (!is_dir(DataProvider::getDataFolder())) throw new ModulePackException(zm_internal_errcode("E00070") . "zm_data dir not found!");
|
||||
$path = realpath(DataProvider::getDataFolder() . "/output");
|
||||
if ($path === false) mkdir($path = DataProvider::getDataFolder() . "/output");
|
||||
if (!is_dir(DataProvider::getDataFolder())) {
|
||||
throw new ModulePackException(zm_internal_errcode('E00070') . 'zm_data dir not found!');
|
||||
}
|
||||
$path = realpath(DataProvider::getDataFolder() . '/output');
|
||||
if ($path === false) {
|
||||
mkdir($path = DataProvider::getDataFolder() . '/output');
|
||||
}
|
||||
$packer->setOutputPath($path);
|
||||
$packer->setOverride();
|
||||
$packer->pack();
|
||||
@@ -106,16 +123,16 @@ class ModuleManager
|
||||
/**
|
||||
* 解包模块
|
||||
* @param $module
|
||||
* @param array $options
|
||||
* @return array|false
|
||||
*/
|
||||
public static function unpackModule($module, array $options = []) {
|
||||
public static function unpackModule($module, array $options = [])
|
||||
{
|
||||
try {
|
||||
$packer = new ModuleUnpacker($module);
|
||||
return $packer->unpack((bool)$options["overwrite-light-cache"], (bool)$options["overwrite-zm-data"], (bool)$options["overwrite-source"], (bool)$options["ignore-depends"]);
|
||||
return $packer->unpack((bool) $options['overwrite-light-cache'], (bool) $options['overwrite-zm-data'], (bool) $options['overwrite-source'], (bool) $options['ignore-depends']);
|
||||
} catch (ZMException $e) {
|
||||
Console::error($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
<?php
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use Swoole\Process;
|
||||
|
||||
class ProcessManager
|
||||
@@ -11,22 +13,13 @@ class ProcessManager
|
||||
/** @var Process[] */
|
||||
public static $user_process = [];
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param callable $callable
|
||||
* @return Process
|
||||
*/
|
||||
public static function createUserProcess(string $name, callable $callable): Process
|
||||
{
|
||||
return self::$user_process[$name] = new Process($callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return Process|null
|
||||
*/
|
||||
public static function getUserProcess(string $string): ?Process
|
||||
{
|
||||
return self::$user_process[$string] ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
use ZM\Annotation\Http\Controller;
|
||||
@@ -15,16 +15,18 @@ use ZM\Store\LightCacheInside;
|
||||
/**
|
||||
* 路由管理器,2.5版本更改了命名空间
|
||||
* Class RouteManager
|
||||
* @package ZM\Utils\Manager
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class RouteManager
|
||||
{
|
||||
/** @var null|RouteCollection */
|
||||
public static $routes = null;
|
||||
public static $routes;
|
||||
|
||||
public static function importRouteByAnnotation(RequestMapping $vss, $method, $class, $methods_annotations) {
|
||||
if (self::$routes === null) self::$routes = new RouteCollection();
|
||||
public static function importRouteByAnnotation(RequestMapping $vss, $method, $class, $methods_annotations)
|
||||
{
|
||||
if (self::$routes === null) {
|
||||
self::$routes = new RouteCollection();
|
||||
}
|
||||
|
||||
// 拿到所属方法的类上面有没有控制器的注解
|
||||
$prefix = '';
|
||||
@@ -34,34 +36,36 @@ class RouteManager
|
||||
break;
|
||||
}
|
||||
}
|
||||
$tail = trim($vss->route, "/");
|
||||
$route_name = $prefix . ($tail === "" ? "" : "/") . $tail;
|
||||
Console::debug("添加路由:" . $route_name);
|
||||
$tail = trim($vss->route, '/');
|
||||
$route_name = $prefix . ($tail === '' ? '' : '/') . $tail;
|
||||
Console::debug('添加路由:' . $route_name);
|
||||
$route = new Route($route_name, ['_class' => $class, '_method' => $method]);
|
||||
$route->setMethods($vss->request_method);
|
||||
|
||||
self::$routes->add(md5($route_name), $route);
|
||||
}
|
||||
|
||||
public static function addStaticFileRoute($route, $path) {
|
||||
$tail = trim($route, "/");
|
||||
$route_name = ($tail === "" ? "" : "/") . $tail . "/{filename}";
|
||||
Console::debug("添加静态文件路由:" . $route_name);
|
||||
$route = new Route($route_name, ['_class' => RouteManager::class, '_method' => "onStaticRoute"]);
|
||||
public static function addStaticFileRoute($route, $path)
|
||||
{
|
||||
$tail = trim($route, '/');
|
||||
$route_name = ($tail === '' ? '' : '/') . $tail . '/{filename}';
|
||||
Console::debug('添加静态文件路由:' . $route_name);
|
||||
$route = new Route($route_name, ['_class' => RouteManager::class, '_method' => 'onStaticRoute']);
|
||||
//echo $path.PHP_EOL;
|
||||
LightCacheInside::set("static_route", $route->getPath(), $path);
|
||||
LightCacheInside::set('static_route', $route->getPath(), $path);
|
||||
|
||||
self::$routes->add(md5($route_name), $route);
|
||||
}
|
||||
|
||||
public function onStaticRoute($params) {
|
||||
$route_path = self::$routes->get($params["_route"])->getPath();
|
||||
if(($path = LightCacheInside::get("static_route", $route_path)) === null) {
|
||||
public function onStaticRoute($params)
|
||||
{
|
||||
$route_path = self::$routes->get($params['_route'])->getPath();
|
||||
if (($path = LightCacheInside::get('static_route', $route_path)) === null) {
|
||||
ctx()->getResponse()->endWithStatus(404);
|
||||
return false;
|
||||
}
|
||||
unset($params["_route"]);
|
||||
unset($params['_route']);
|
||||
$obj = array_shift($params);
|
||||
return new StaticFileHandler($obj, $path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
<?php
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
|
||||
use ZM\Console\Console;
|
||||
|
||||
class TaskManager
|
||||
{
|
||||
/**
|
||||
* @param $task_name
|
||||
* @param int $timeout
|
||||
* @param mixed ...$params
|
||||
* @param mixed ...$params
|
||||
* @return false|mixed
|
||||
*/
|
||||
public static function runTask($task_name, int $timeout = -1, ...$params) {
|
||||
if (!isset(server()->setting["task_worker_num"])) {
|
||||
Console::warning(zm_internal_errcode("E00056") . "未开启 TaskWorker 进程,请先修改 global 配置文件启用!");
|
||||
public static function runTask($task_name, int $timeout = -1, ...$params)
|
||||
{
|
||||
if (!isset(server()->setting['task_worker_num'])) {
|
||||
Console::warning(zm_internal_errcode('E00056') . '未开启 TaskWorker 进程,请先修改 global 配置文件启用!');
|
||||
return false;
|
||||
}
|
||||
$r = server()->taskwait(["task" => $task_name, "params" => $params], $timeout);
|
||||
return $r === false ? false : $r["result"];
|
||||
$r = server()->taskwait(['task' => $task_name, 'params' => $params], $timeout);
|
||||
return $r === false ? false : $r['result'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils\Manager;
|
||||
|
||||
use Exception;
|
||||
@@ -24,78 +26,78 @@ class WorkerManager
|
||||
public static function workerAction($src_worker_id, $data)
|
||||
{
|
||||
$server = server();
|
||||
switch ($data["action"] ?? '') {
|
||||
switch ($data['action'] ?? '') {
|
||||
case 'add_short_command':
|
||||
Console::verbose("Adding short command " . $data["data"][0]);
|
||||
Console::verbose('Adding short command ' . $data['data'][0]);
|
||||
$obj = new CQCommand();
|
||||
$obj->method = quick_reply_closure($data["data"][1]);
|
||||
$obj->match = $data["data"][0];
|
||||
$obj->class = "";
|
||||
$obj->method = quick_reply_closure($data['data'][1]);
|
||||
$obj->match = $data['data'][0];
|
||||
$obj->class = '';
|
||||
EventManager::addEvent(CQCommand::class, $obj);
|
||||
break;
|
||||
case "eval":
|
||||
eval($data["data"]);
|
||||
case 'eval':
|
||||
eval($data['data']);
|
||||
break;
|
||||
case "call_static":
|
||||
call_user_func_array([$data["data"]["class"], $data["data"]["method"]], $data["data"]["params"]);
|
||||
case 'call_static':
|
||||
call_user_func_array([$data['data']['class'], $data['data']['method']], $data['data']['params']);
|
||||
break;
|
||||
case "save_persistence":
|
||||
case 'save_persistence':
|
||||
LightCache::savePersistence();
|
||||
break;
|
||||
case "resume_ws_message":
|
||||
$obj = $data["data"];
|
||||
Coroutine::resume($obj["coroutine"]);
|
||||
case 'resume_ws_message':
|
||||
$obj = $data['data'];
|
||||
Coroutine::resume($obj['coroutine']);
|
||||
break;
|
||||
case "getWorkerCache":
|
||||
$r = WorkerCache::get($data["key"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
case 'getWorkerCache':
|
||||
$r = WorkerCache::get($data['key']);
|
||||
$action = ['action' => 'returnWorkerCache', 'cid' => $data['cid'], 'value' => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "setWorkerCache":
|
||||
$r = WorkerCache::set($data["key"], $data["value"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
case 'setWorkerCache':
|
||||
$r = WorkerCache::set($data['key'], $data['value']);
|
||||
$action = ['action' => 'returnWorkerCache', 'cid' => $data['cid'], 'value' => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "unsetWorkerCache":
|
||||
$r = WorkerCache::unset($data["key"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
case 'unsetWorkerCache':
|
||||
$r = WorkerCache::unset($data['key']);
|
||||
$action = ['action' => 'returnWorkerCache', 'cid' => $data['cid'], 'value' => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "hasKeyWorkerCache":
|
||||
$r = WorkerCache::hasKey($data["key"], $data["subkey"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
case 'hasKeyWorkerCache':
|
||||
$r = WorkerCache::hasKey($data['key'], $data['subkey']);
|
||||
$action = ['action' => 'returnWorkerCache', 'cid' => $data['cid'], 'value' => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "asyncAddWorkerCache":
|
||||
WorkerCache::add($data["key"], $data["value"], true);
|
||||
case 'asyncAddWorkerCache':
|
||||
WorkerCache::add($data['key'], $data['value'], true);
|
||||
break;
|
||||
case "asyncSubWorkerCache":
|
||||
WorkerCache::sub($data["key"], $data["value"], true);
|
||||
case 'asyncSubWorkerCache':
|
||||
WorkerCache::sub($data['key'], $data['value'], true);
|
||||
break;
|
||||
case "asyncSetWorkerCache":
|
||||
WorkerCache::set($data["key"], $data["value"], true);
|
||||
case 'asyncSetWorkerCache':
|
||||
WorkerCache::set($data['key'], $data['value'], true);
|
||||
break;
|
||||
case "asyncUnsetWorkerCache":
|
||||
WorkerCache::unset($data["key"], true);
|
||||
case 'asyncUnsetWorkerCache':
|
||||
WorkerCache::unset($data['key'], true);
|
||||
break;
|
||||
case "addWorkerCache":
|
||||
$r = WorkerCache::add($data["key"], $data["value"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
case 'addWorkerCache':
|
||||
$r = WorkerCache::add($data['key'], $data['value']);
|
||||
$action = ['action' => 'returnWorkerCache', 'cid' => $data['cid'], 'value' => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "subWorkerCache":
|
||||
$r = WorkerCache::sub($data["key"], $data["value"]);
|
||||
$action = ["action" => "returnWorkerCache", "cid" => $data["cid"], "value" => $r];
|
||||
case 'subWorkerCache':
|
||||
$r = WorkerCache::sub($data['key'], $data['value']);
|
||||
$action = ['action' => 'returnWorkerCache', 'cid' => $data['cid'], 'value' => $r];
|
||||
$server->sendMessage(json_encode($action, 256), $src_worker_id);
|
||||
break;
|
||||
case "returnWorkerCache":
|
||||
WorkerCache::$transfer[$data["cid"]] = $data["value"];
|
||||
zm_resume($data["cid"]);
|
||||
case 'returnWorkerCache':
|
||||
WorkerCache::$transfer[$data['cid']] = $data['value'];
|
||||
zm_resume($data['cid']);
|
||||
break;
|
||||
default:
|
||||
$dispatcher = new EventDispatcher(OnPipeMessageEvent::class);
|
||||
$dispatcher->setRuleFunction(function (OnPipeMessageEvent $v) use ($data) {
|
||||
return $v->action == $data["action"];
|
||||
return $v->action == $data['action'];
|
||||
});
|
||||
$dispatcher->dispatchEvents($data);
|
||||
break;
|
||||
@@ -111,9 +113,9 @@ class WorkerManager
|
||||
*/
|
||||
public static function sendActionToWorker($worker_id, $action, $data)
|
||||
{
|
||||
$obj = ["action" => $action, "data" => $data];
|
||||
$obj = ['action' => $action, 'data' => $data];
|
||||
if (server()->worker_id === -1 && server()->getManagerPid() != posix_getpid()) {
|
||||
Console::warning(zm_internal_errcode("E00022") . "Cannot send worker action from master or manager process!");
|
||||
Console::warning(zm_internal_errcode('E00022') . 'Cannot send worker action from master or manager process!');
|
||||
return;
|
||||
}
|
||||
if (server()->worker_id == $worker_id) {
|
||||
@@ -132,10 +134,12 @@ class WorkerManager
|
||||
Console::warning("Cannot call '" . __FUNCTION__ . "' in non-worker process!");
|
||||
return;
|
||||
}
|
||||
foreach ((LightCacheInside::get("wait_api", "wait_api") ?? []) as $v) {
|
||||
if (isset($v["coroutine"], $v["worker_id"])) {
|
||||
if (server()->worker_id == $v["worker_id"]) Coroutine::resume($v["coroutine"]);
|
||||
foreach ((LightCacheInside::get('wait_api', 'wait_api') ?? []) as $v) {
|
||||
if (isset($v['coroutine'], $v['worker_id'])) {
|
||||
if (server()->worker_id == $v['worker_id']) {
|
||||
Coroutine::resume($v['coroutine']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Exception;
|
||||
use ZM\Annotation\CQ\CQCommand;
|
||||
use ZM\API\CQ;
|
||||
use ZM\Config\ZMConfig;
|
||||
@@ -11,34 +12,37 @@ use ZM\Console\Console;
|
||||
use ZM\Entity\MatchResult;
|
||||
use ZM\Event\EventManager;
|
||||
use ZM\Requests\ZMRequest;
|
||||
use ZM\Utils\Manager\ProcessManager;
|
||||
use ZM\Utils\Manager\WorkerManager;
|
||||
|
||||
class MessageUtil
|
||||
{
|
||||
/**
|
||||
* 下载消息中 CQ 码的所有图片,通过 url
|
||||
* @param $msg
|
||||
* @param null $path
|
||||
* @param null $path
|
||||
* @return array|false
|
||||
*/
|
||||
public static function downloadCQImage($msg, $path = null) {
|
||||
$path = $path ?? DataProvider::getDataFolder() . "images/";
|
||||
if (!is_dir($path)) @mkdir($path);
|
||||
public static function downloadCQImage($msg, $path = null)
|
||||
{
|
||||
$path = $path ?? DataProvider::getDataFolder() . 'images/';
|
||||
if (!is_dir($path)) {
|
||||
@mkdir($path);
|
||||
}
|
||||
$path = realpath($path);
|
||||
if ($path === false) {
|
||||
Console::warning(zm_internal_errcode("E00059") . "指定的路径错误不存在!");
|
||||
Console::warning(zm_internal_errcode('E00059') . '指定的路径错误不存在!');
|
||||
return false;
|
||||
}
|
||||
$files = [];
|
||||
$cq = CQ::getAllCQ($msg, true);
|
||||
foreach ($cq as $v) {
|
||||
if ($v->type == "image") {
|
||||
$result = ZMRequest::downloadFile($v->params["url"], $path . "/" . $v->params["file"]);
|
||||
if ($v->type == 'image') {
|
||||
$result = ZMRequest::downloadFile($v->params['url'], $path . '/' . $v->params['file']);
|
||||
if ($result === false) {
|
||||
Console::warning(zm_internal_errcode("E00060") . "图片 " . $v->params["url"] . " 下载失败!");
|
||||
Console::warning(zm_internal_errcode('E00060') . '图片 ' . $v->params['url'] . ' 下载失败!');
|
||||
return false;
|
||||
}
|
||||
$files[] = $path . "/" . $v->params["file"];
|
||||
$files[] = $path . '/' . $v->params['file'];
|
||||
}
|
||||
}
|
||||
return $files;
|
||||
@@ -47,19 +51,20 @@ class MessageUtil
|
||||
/**
|
||||
* 检查消息中是否含有图片 CQ 码
|
||||
* @param $msg
|
||||
* @return bool
|
||||
*/
|
||||
public static function containsImage($msg): bool {
|
||||
public static function containsImage($msg): bool
|
||||
{
|
||||
$cq = CQ::getAllCQ($msg, true);
|
||||
foreach ($cq as $v) {
|
||||
if ($v->type == "image") {
|
||||
if ($v->type == 'image') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isAtMe($msg, $me_id): bool {
|
||||
public static function isAtMe($msg, $me_id): bool
|
||||
{
|
||||
return strpos($msg, CQ::at($me_id)) !== false;
|
||||
}
|
||||
|
||||
@@ -69,20 +74,19 @@ class MessageUtil
|
||||
* type == 1 : 返回图片的 file://路径 CQ 码(路径必须为绝对路径)
|
||||
* type == 2 : 返回图片的 http://xxx CQ 码(默认为 /images/ 路径就是文件对应所在的目录)
|
||||
* @param $file
|
||||
* @param int $type
|
||||
* @return string
|
||||
*/
|
||||
public static function getImageCQFromLocal($file, int $type = 0): string {
|
||||
public static function getImageCQFromLocal($file, int $type = 0): string
|
||||
{
|
||||
switch ($type) {
|
||||
case 0:
|
||||
return CQ::image("base64://" . base64_encode(file_get_contents($file)));
|
||||
return CQ::image('base64://' . base64_encode(file_get_contents($file)));
|
||||
case 1:
|
||||
return CQ::image("file://" . $file);
|
||||
return CQ::image('file://' . $file);
|
||||
case 2:
|
||||
$info = pathinfo($file);
|
||||
return CQ::image(ZMConfig::get("global", "http_reverse_link") . "/images/" . $info["basename"]);
|
||||
return CQ::image(ZMConfig::get('global', 'http_reverse_link') . '/images/' . $info['basename']);
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,12 +94,15 @@ class MessageUtil
|
||||
* @param $msg
|
||||
* @return array|string[]
|
||||
*/
|
||||
public static function splitCommand($msg): array {
|
||||
$word = explodeMsg(str_replace("\r", "", $msg));
|
||||
if (empty($word)) $word = [""];
|
||||
public static function splitCommand($msg): array
|
||||
{
|
||||
$word = explodeMsg(str_replace("\r", '', $msg));
|
||||
if (empty($word)) {
|
||||
$word = [''];
|
||||
}
|
||||
if (count(explode("\n", $word[0])) >= 2) {
|
||||
$enter = explode("\n", $msg);
|
||||
$first = split_explode(" ", array_shift($enter));
|
||||
$first = split_explode(' ', array_shift($enter));
|
||||
$word = array_merge($first, $enter);
|
||||
foreach ($word as $k => $v) {
|
||||
$word[$k] = trim($v);
|
||||
@@ -107,9 +114,9 @@ class MessageUtil
|
||||
/**
|
||||
* @param $msg
|
||||
* @param $obj
|
||||
* @return MatchResult
|
||||
*/
|
||||
public static function matchCommand($msg, $obj): MatchResult {
|
||||
public static function matchCommand($msg, $obj): MatchResult
|
||||
{
|
||||
$ls = EventManager::$events[CQCommand::class] ?? [];
|
||||
if (is_array($msg)) {
|
||||
$msg = self::arrayToStr($msg);
|
||||
@@ -117,33 +124,39 @@ class MessageUtil
|
||||
$word = self::splitCommand($msg);
|
||||
$matched = new MatchResult();
|
||||
foreach ($ls as $v) {
|
||||
if (array_diff([$v->match, $v->pattern, $v->regex, $v->keyword, $v->end_with, $v->start_with], [""]) == []) continue;
|
||||
elseif (($v->user_id == 0 || ($v->user_id == $obj["user_id"])) &&
|
||||
($v->group_id == 0 || ($v->group_id == ($obj["group_id"] ?? 0))) &&
|
||||
($v->message_type == '' || ($v->message_type == $obj["message_type"]))
|
||||
if (array_diff([$v->match, $v->pattern, $v->regex, $v->keyword, $v->end_with, $v->start_with], ['']) == []) {
|
||||
continue;
|
||||
}
|
||||
if (($v->user_id == 0 || ($v->user_id == $obj['user_id']))
|
||||
&& ($v->group_id == 0 || ($v->group_id == ($obj['group_id'] ?? 0)))
|
||||
&& ($v->message_type == '' || ($v->message_type == $obj['message_type']))
|
||||
) {
|
||||
if (($word[0] != "" && $v->match == $word[0]) || in_array($word[0], $v->alias)) {
|
||||
if (($word[0] != '' && $v->match == $word[0]) || in_array($word[0], $v->alias)) {
|
||||
array_shift($word);
|
||||
$matched->match = $word;
|
||||
$matched->object = $v;
|
||||
$matched->status = true;
|
||||
break;
|
||||
} elseif ($v->start_with != "" && mb_substr($msg, 0, mb_strlen($v->start_with)) === $v->start_with) {
|
||||
}
|
||||
if ($v->start_with != '' && mb_substr($msg, 0, mb_strlen($v->start_with)) === $v->start_with) {
|
||||
$matched->match = [mb_substr($msg, mb_strlen($v->start_with))];
|
||||
$matched->object = $v;
|
||||
$matched->status = true;
|
||||
break;
|
||||
} elseif ($v->end_with != "" && mb_substr($msg, 0 - mb_strlen($v->end_with)) === $v->end_with) {
|
||||
}
|
||||
if ($v->end_with != '' && mb_substr($msg, 0 - mb_strlen($v->end_with)) === $v->end_with) {
|
||||
$matched->match = [substr($msg, 0, strripos($msg, $v->end_with))];
|
||||
$matched->object = $v;
|
||||
$matched->status = true;
|
||||
break;
|
||||
} elseif ($v->keyword != "" && mb_strpos($msg, $v->keyword) !== false) {
|
||||
}
|
||||
if ($v->keyword != '' && mb_strpos($msg, $v->keyword) !== false) {
|
||||
$matched->match = explode($v->keyword, $msg);
|
||||
$matched->object = $v;
|
||||
$matched->status = true;
|
||||
break;
|
||||
} elseif ($v->pattern != "") {
|
||||
}
|
||||
if ($v->pattern != '') {
|
||||
$match = matchArgs($v->pattern, $msg);
|
||||
if ($match !== false) {
|
||||
$matched->match = $match;
|
||||
@@ -151,8 +164,8 @@ class MessageUtil
|
||||
$matched->status = true;
|
||||
break;
|
||||
}
|
||||
} elseif ($v->regex != "") {
|
||||
if (preg_match("/" . $v->regex . "/u", $msg, $word2) != 0) {
|
||||
} elseif ($v->regex != '') {
|
||||
if (preg_match('/' . $v->regex . '/u', $msg, $word2) != 0) {
|
||||
$matched->match = $word2;
|
||||
$matched->object = $v;
|
||||
$matched->status = true;
|
||||
@@ -164,20 +177,24 @@ class MessageUtil
|
||||
return $matched;
|
||||
}
|
||||
|
||||
public static function addShortCommand($command, string $reply) {
|
||||
/**
|
||||
* @param $command
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function addShortCommand($command, string $reply)
|
||||
{
|
||||
for ($i = 0; $i < ZM_WORKER_NUM; ++$i) {
|
||||
ProcessManager::sendActionToWorker($i, "add_short_command", [$command, $reply]);
|
||||
WorkerManager::sendActionToWorker($i, 'add_short_command', [$command, $reply]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转数组
|
||||
* @param $msg
|
||||
* @param bool $ignore_space
|
||||
* @param false $trim_text
|
||||
* @return array
|
||||
*/
|
||||
public static function strToArray($msg, bool $ignore_space = true, bool $trim_text = false): array {
|
||||
public static function strToArray($msg, bool $ignore_space = true, bool $trim_text = false): array
|
||||
{
|
||||
$arr = [];
|
||||
while (($rear = mb_strstr($msg, '[CQ:')) !== false && ($end = mb_strstr($rear, ']', true)) !== false) {
|
||||
// 把 [CQ: 前面的文字生成段落
|
||||
@@ -188,14 +205,14 @@ class MessageUtil
|
||||
}
|
||||
// 处理 CQ 码
|
||||
$content = mb_substr($end, 4);
|
||||
$cq = explode(",", $content);
|
||||
$cq = explode(',', $content);
|
||||
$object_type = array_shift($cq);
|
||||
$object_params = [];
|
||||
foreach ($cq as $v) {
|
||||
$key = mb_strstr($v, "=", true);
|
||||
$object_params[$key] = CQ::decode(mb_substr(mb_strstr($v, "="), 1), true);
|
||||
$key = mb_strstr($v, '=', true);
|
||||
$object_params[$key] = CQ::decode(mb_substr(mb_strstr($v, '='), 1), true);
|
||||
}
|
||||
$arr[] = ["type" => $object_type, "data" => $object_params];
|
||||
$arr[] = ['type' => $object_type, 'data' => $object_params];
|
||||
$msg = mb_substr(mb_strstr($rear, ']'), 1);
|
||||
}
|
||||
if (($trim_msg = trim($msg)) !== '' || ($msg !== '' && !$ignore_space)) {
|
||||
@@ -207,23 +224,22 @@ class MessageUtil
|
||||
/**
|
||||
* 数组转字符串
|
||||
* 纪念一下,这段代码完全由AI生成,没有人知道它是怎么写的,这句话是我自己写的,不知道是不是有人知道的
|
||||
* @param array $array
|
||||
* @return string
|
||||
* @author Copilot
|
||||
*/
|
||||
public static function arrayToStr(array $array): string {
|
||||
$str = "";
|
||||
public static function arrayToStr(array $array): string
|
||||
{
|
||||
$str = '';
|
||||
foreach ($array as $v) {
|
||||
if ($v['type'] == 'text') {
|
||||
$str .= $v['data']['text'];
|
||||
} else {
|
||||
$str .= "[CQ:" . $v['type'];
|
||||
$str .= '[CQ:' . $v['type'];
|
||||
foreach ($v['data'] as $key => $value) {
|
||||
$str .= "," . $key . "=" . CQ::encode($value, true);
|
||||
$str .= ',' . $key . '=' . CQ::encode($value, true);
|
||||
}
|
||||
$str .= "]";
|
||||
$str .= ']';
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Swoole\Process;
|
||||
use Swoole\Server;
|
||||
use ZM\Console\Console;
|
||||
@@ -11,26 +11,26 @@ use ZM\Console\Console;
|
||||
/**
|
||||
* 炸毛框架的Linux signal管理类
|
||||
* Class SignalListener
|
||||
* @package ZM\Utils
|
||||
* @since 2.5
|
||||
*/
|
||||
class SignalListener
|
||||
{
|
||||
private static $manager_kill_time = 0;
|
||||
|
||||
/**
|
||||
* 监听Master进程的Ctrl+C
|
||||
* @param Server $server
|
||||
*/
|
||||
public static function signalMaster(Server $server) {
|
||||
Console::debug("Listening Master SIGINT");
|
||||
public static function signalMaster(Server $server)
|
||||
{
|
||||
Console::debug('Listening Master SIGINT');
|
||||
Process::signal(SIGINT, function () use ($server) {
|
||||
if (zm_atomic("_int_is_reload")->get() === 1) {
|
||||
zm_atomic("_int_is_reload")->set(0);
|
||||
if (zm_atomic('_int_is_reload')->get() === 1) {
|
||||
zm_atomic('_int_is_reload')->set(0);
|
||||
$server->reload();
|
||||
} else {
|
||||
echo "\r";
|
||||
Console::warning("Server interrupted(SIGINT) on Master.");
|
||||
Console::warning("Server will be shutdown.");
|
||||
Console::warning('Server interrupted(SIGINT) on Master.');
|
||||
Console::warning('Server will be shutdown.');
|
||||
Process::kill($server->master_pid, SIGTERM);
|
||||
}
|
||||
});
|
||||
@@ -39,39 +39,40 @@ class SignalListener
|
||||
/**
|
||||
* 监听Manager进程的Ctrl+C
|
||||
*/
|
||||
public static function signalManager() {
|
||||
public static function signalManager()
|
||||
{
|
||||
$func = function () {
|
||||
if (\server()->master_pid == \server()->manager_pid) {
|
||||
echo "\r";
|
||||
Console::warning("Server interrupted(SIGINT) on Manager.");
|
||||
swoole_timer_after(2, function() {
|
||||
Console::warning('Server interrupted(SIGINT) on Manager.');
|
||||
swoole_timer_after(2, function () {
|
||||
Process::kill(posix_getpid(), SIGTERM);
|
||||
});
|
||||
} else {
|
||||
Console::verbose("Interrupted in manager!");
|
||||
Console::verbose('Interrupted in manager!');
|
||||
}
|
||||
self::processKillerPrompt();
|
||||
};
|
||||
Console::debug("Listening Manager SIGINT");
|
||||
if (version_compare(SWOOLE_VERSION, "4.6.7") >= 0) {
|
||||
Console::debug('Listening Manager SIGINT');
|
||||
if (version_compare(SWOOLE_VERSION, '4.6.7') >= 0) {
|
||||
Process::signal(SIGINT, $func);
|
||||
} elseif (extension_loaded("pcntl")) {
|
||||
} elseif (extension_loaded('pcntl')) {
|
||||
pcntl_signal(SIGINT, $func);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听Worker/TaskWorker进程的Ctrl+C
|
||||
* @param Server $server
|
||||
* @param $worker_id
|
||||
*/
|
||||
public static function signalWorker(Server $server, $worker_id) {
|
||||
Console::debug("Listening Worker #".$worker_id." SIGINT");
|
||||
Process::signal(SIGINT, function () use ($worker_id, $server) {
|
||||
public static function signalWorker(Server $server, $worker_id)
|
||||
{
|
||||
Console::debug('Listening Worker #' . $worker_id . ' SIGINT');
|
||||
Process::signal(SIGINT, function () use ($server) {
|
||||
if ($server->master_pid == $server->worker_pid) { // 当Swoole以单进程模型运行的时候,Worker需要监听杀死的信号
|
||||
echo "\r";
|
||||
Console::warning("Server interrupted(SIGINT) on Worker.");
|
||||
swoole_timer_after(2, function() {
|
||||
Console::warning('Server interrupted(SIGINT) on Worker.');
|
||||
swoole_timer_after(2, function () {
|
||||
Process::kill(posix_getpid(), SIGTERM);
|
||||
});
|
||||
self::processKillerPrompt();
|
||||
@@ -84,24 +85,25 @@ class SignalListener
|
||||
/**
|
||||
* 按5次Ctrl+C后强行杀死框架的处理函数
|
||||
*/
|
||||
private static function processKillerPrompt() {
|
||||
private static function processKillerPrompt()
|
||||
{
|
||||
if (self::$manager_kill_time > 0) {
|
||||
if (self::$manager_kill_time >= 5) {
|
||||
$file_path = _zm_pid_dir();
|
||||
$flist = DataProvider::scanDirFiles($file_path, false, true);
|
||||
foreach($flist as $file) {
|
||||
foreach ($flist as $file) {
|
||||
$name = explode('.', $file);
|
||||
if (end($name) == 'pid' && $name[0] !== 'manager') {
|
||||
$pid = file_get_contents($file_path.'/'.$file);
|
||||
$pid = file_get_contents($file_path . '/' . $file);
|
||||
Process::kill($pid, SIGKILL);
|
||||
}
|
||||
unlink($file_path.'/'.$file);
|
||||
unlink($file_path . '/' . $file);
|
||||
}
|
||||
} else {
|
||||
echo "\r";
|
||||
Console::log("再按" . (5 - self::$manager_kill_time) . "次Ctrl+C所有Worker进程就会被强制杀死", 'red');
|
||||
Console::log('再按' . (5 - self::$manager_kill_time) . '次Ctrl+C所有Worker进程就会被强制杀死', 'red');
|
||||
}
|
||||
}
|
||||
self::$manager_kill_time++;
|
||||
++self::$manager_kill_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
<?php
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
trait SingletonTrait
|
||||
{
|
||||
protected static $cached = [];
|
||||
|
||||
/**
|
||||
* @var self
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
protected static $cached = [];
|
||||
|
||||
/**
|
||||
* @return self
|
||||
* @noinspection PhpMissingReturnTypeInspection
|
||||
*/
|
||||
public static function getInstance() {
|
||||
if (null === self::$instance) {
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<?php /** @noinspection PhpUnused */
|
||||
<?php
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
@@ -19,52 +21,54 @@ class Terminal
|
||||
public static $default_commands = false;
|
||||
|
||||
/**
|
||||
* @param string $cmd
|
||||
* @throws Exception
|
||||
* @return bool
|
||||
* @noinspection PhpMissingReturnTypeInspection
|
||||
* @noinspection PhpUnused
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function executeCommand(string $cmd) {
|
||||
public static function executeCommand(string $cmd)
|
||||
{
|
||||
if (self::$default_commands === false) {
|
||||
self::init();
|
||||
}
|
||||
$it = explodeMsg($cmd);
|
||||
$dispatcher = new EventDispatcher(TerminalCommand::class);
|
||||
$dispatcher->setRuleFunction(function ($v) use ($it) {
|
||||
/** @var TerminalCommand $v */
|
||||
/* @var TerminalCommand $v */
|
||||
return !empty($it) && ($v->command == $it[0] || $v->alias == $it[0]);
|
||||
});
|
||||
$dispatcher->setReturnFunction(function () {
|
||||
EventDispatcher::interrupt('none');
|
||||
});
|
||||
$dispatcher->dispatchEvents($it);
|
||||
if ($dispatcher->store !== 'none' && $cmd !== "") {
|
||||
Console::info("Command not found: " . $cmd);
|
||||
if ($dispatcher->store !== 'none' && $cmd !== '') {
|
||||
Console::info('Command not found: ' . $cmd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function log($type, $log_msg) {
|
||||
public static function log($type, $log_msg)
|
||||
{
|
||||
ob_start();
|
||||
if (!in_array($type, ["log", "info", "debug", "success", "warning", "error", "verbose"])) {
|
||||
if (!in_array($type, ['log', 'info', 'debug', 'success', 'warning', 'error', 'verbose'])) {
|
||||
ob_get_clean();
|
||||
return;
|
||||
}
|
||||
Console::$type($log_msg);
|
||||
$r = ob_get_clean();
|
||||
$all = ManagerGM::getAllByName("terminal");
|
||||
$all = ManagerGM::getAllByName('terminal');
|
||||
foreach ($all as $v) {
|
||||
server()->send($v->getFd(), "\r" . $r);
|
||||
server()->send($v->getFd(), ">>> ");
|
||||
server()->send($v->getFd(), '>>> ');
|
||||
}
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
Console::debug("Initializing Terminal...");
|
||||
public static function init()
|
||||
{
|
||||
Console::debug('Initializing Terminal...');
|
||||
foreach ((EventManager::$events[TerminalCommand::class] ?? []) as $v) {
|
||||
if ($v->command == "help") {
|
||||
if ($v->command == 'help') {
|
||||
self::$default_commands = true;
|
||||
break;
|
||||
}
|
||||
@@ -75,7 +79,7 @@ class Terminal
|
||||
foreach ($reflection->getMethods() as $v) {
|
||||
$r = $reader->getMethodAnnotation($v, TerminalCommand::class);
|
||||
if ($r !== null) {
|
||||
Console::debug("adding command " . $r->command);
|
||||
Console::debug('adding command ' . $r->command);
|
||||
$r->class = Terminal::class;
|
||||
$r->method = $v->getName();
|
||||
EventManager::addEvent(TerminalCommand::class, $r);
|
||||
@@ -87,13 +91,14 @@ class Terminal
|
||||
/**
|
||||
* @TerminalCommand(command="help",alias="h",description="显示帮助菜单")
|
||||
*/
|
||||
public function help() {
|
||||
public function help()
|
||||
{
|
||||
$help = [];
|
||||
foreach ((EventManager::$events[TerminalCommand::class] ?? []) as $v) {
|
||||
/** @var TerminalCommand $v */
|
||||
$cmd = $v->command . ($v->alias !== "" ? (" | " . $v->alias) : "");
|
||||
$painted = Console::setColor($v->command, "green") . ($v->alias !== "" ? (" | " . Console::setColor($v->alias, "green")) : "");
|
||||
$help[] = $painted . ":" . str_pad("", 16 - strlen($cmd) - 1) . ($v->description === "" ? "<无描述>" : $v->description);
|
||||
$cmd = $v->command . ($v->alias !== '' ? (' | ' . $v->alias) : '');
|
||||
$painted = Console::setColor($v->command, 'green') . ($v->alias !== '' ? (' | ' . Console::setColor($v->alias, 'green')) : '');
|
||||
$help[] = $painted . ':' . str_pad('', 16 - strlen($cmd) - 1) . ($v->description === '' ? '<无描述>' : $v->description);
|
||||
}
|
||||
echo implode("\n", $help) . PHP_EOL;
|
||||
}
|
||||
@@ -102,61 +107,71 @@ class Terminal
|
||||
* @TerminalCommand(command="status",description="显示Swoole Server运行状态(需要安装league/climate组件)")
|
||||
* @noinspection PhpFullyQualifiedNameUsageInspection
|
||||
*/
|
||||
public function status() {
|
||||
if (!class_exists("\League\CLImate\CLImate")) {
|
||||
Console::warning("你还没有安装 league/climate 组件,无法使用此功能!");
|
||||
public function status()
|
||||
{
|
||||
if (!class_exists('\\League\\CLImate\\CLImate')) {
|
||||
Console::warning('你还没有安装 league/climate 组件,无法使用此功能!');
|
||||
return;
|
||||
}
|
||||
$climate = new \League\CLImate\CLImate;
|
||||
$climate = new \League\CLImate\CLImate();
|
||||
$climate->output->addDefault('buffer');
|
||||
|
||||
$objs = server()->stats();
|
||||
$climate->columns($objs);
|
||||
$obj = $climate->output->get('buffer')->get();
|
||||
$climate->output->get("buffer")->clean();
|
||||
$climate->output->get('buffer')->clean();
|
||||
echo $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @TerminalCommand(command="logtest",description="测试log的显示等级")
|
||||
*/
|
||||
public function testlog() {
|
||||
Console::log(date("[H:i:s]") . " [L] This is normal msg. (0)");
|
||||
Console::error("This is error msg. (0)");
|
||||
Console::warning("This is warning msg. (1)");
|
||||
Console::info("This is info msg. (2)");
|
||||
Console::success("This is success msg. (2)");
|
||||
Console::verbose("This is verbose msg. (3)");
|
||||
Console::debug("This is debug msg. (4)");
|
||||
public function testlog()
|
||||
{
|
||||
Console::log(date('[H:i:s]') . ' [L] This is normal msg. (0)');
|
||||
Console::error('This is error msg. (0)');
|
||||
Console::warning('This is warning msg. (1)');
|
||||
Console::info('This is info msg. (2)');
|
||||
Console::success('This is success msg. (2)');
|
||||
Console::verbose('This is verbose msg. (3)');
|
||||
Console::debug('This is debug msg. (4)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @TerminalCommand(command="call",description="用于执行不需要参数的动态函数,比如 `call \Module\Example\Hello hitokoto`")
|
||||
* @param $it
|
||||
*/
|
||||
public function call($it) {
|
||||
public function call($it)
|
||||
{
|
||||
$class_name = $it[1];
|
||||
$function_name = $it[2];
|
||||
$class = new $class_name([]);
|
||||
$r = $class->$function_name();
|
||||
if (is_string($r)) Console::success($r);
|
||||
$r = $class->{$function_name}();
|
||||
if (is_string($r)) {
|
||||
Console::success($r);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @TerminalCommand(command="level",description="设置log等级,例如 `level 0|1|2|3|4`")
|
||||
* @param $it
|
||||
*/
|
||||
public function level($it) {
|
||||
public function level($it)
|
||||
{
|
||||
$level = intval(is_numeric($it[1] ?? 99) ? ($it[1] ?? 99) : 99);
|
||||
if ($level > 4 || $level < 0) Console::warning("Usage: 'level 0|1|2|3|4'");
|
||||
else Console::setLevel($level) || Console::success("Success!!");
|
||||
if ($level > 4 || $level < 0) {
|
||||
Console::warning("Usage: 'level 0|1|2|3|4'");
|
||||
} else {
|
||||
Console::setLevel($level) || Console::success('Success!!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @TerminalCommand(command="bc",description="eval执行代码,但输入必须是将代码base64之后的,如 `bc em1faW5mbygn5L2g5aW9Jyk7`")
|
||||
* @param $it
|
||||
*/
|
||||
public function bc($it) {
|
||||
public function bc($it)
|
||||
{
|
||||
$code = base64_decode($it[1] ?? '', true);
|
||||
try {
|
||||
eval($code);
|
||||
@@ -168,21 +183,24 @@ class Terminal
|
||||
* @TerminalCommand(command="echo",description="输出内容,用法:`echo hello`")
|
||||
* @param $it
|
||||
*/
|
||||
public function echoI($it) {
|
||||
public function echoI($it)
|
||||
{
|
||||
Console::info($it[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TerminalCommand(command="stop",description="停止框架")
|
||||
*/
|
||||
public function stop() {
|
||||
public function stop()
|
||||
{
|
||||
posix_kill(server()->master_pid, SIGTERM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @TerminalCommand(command="reload",alias="r",description="重启框架(重载用户代码)")
|
||||
*/
|
||||
public function reload() {
|
||||
public function reload()
|
||||
{
|
||||
Process::kill(server()->master_pid, SIGUSR1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Utils;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Swoole\Process;
|
||||
use ZM\Console\Console;
|
||||
@@ -28,10 +28,15 @@ class ZMUtil
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function stop() {
|
||||
if (SpinLock::tryLock('_stop_signal') === false) return;
|
||||
public static function stop()
|
||||
{
|
||||
if (SpinLock::tryLock('_stop_signal') === false) {
|
||||
return;
|
||||
}
|
||||
Console::warning(Console::setColor('Stopping server...', 'red'));
|
||||
if (Console::getLevel() >= 4) Console::trace();
|
||||
if (Console::getLevel() >= 4) {
|
||||
Console::trace();
|
||||
}
|
||||
ZMAtomic::get('stop_signal')->set(1);
|
||||
server()->shutdown();
|
||||
}
|
||||
@@ -39,29 +44,31 @@ class ZMUtil
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function reload() {
|
||||
public static function reload()
|
||||
{
|
||||
Process::kill(server()->master_pid, SIGUSR1);
|
||||
}
|
||||
|
||||
public static function getModInstance($class) {
|
||||
public static function getModInstance($class)
|
||||
{
|
||||
if (!isset(ZMBuf::$instance[$class])) {
|
||||
//Console::debug('Class instance $class not exist, so I created it.');
|
||||
return ZMBuf::$instance[$class] = new $class();
|
||||
} else {
|
||||
return ZMBuf::$instance[$class];
|
||||
}
|
||||
return ZMBuf::$instance[$class];
|
||||
}
|
||||
|
||||
/**
|
||||
* 在工作进程中返回可以通过reload重新加载的php文件列表
|
||||
* @return string[]|string[][]
|
||||
*/
|
||||
public static function getReloadableFiles(): array {
|
||||
public static function getReloadableFiles(): array
|
||||
{
|
||||
$array_map = [];
|
||||
foreach (array_diff(
|
||||
get_included_files(),
|
||||
Framework::$loaded_files
|
||||
) as $key => $x) {
|
||||
get_included_files(),
|
||||
Framework::$loaded_files
|
||||
) as $key => $x) {
|
||||
$array_map[$key] = str_replace(DataProvider::getSourceRootDir() . '/', '', $x);
|
||||
}
|
||||
return $array_map;
|
||||
@@ -71,11 +78,12 @@ class ZMUtil
|
||||
* 使用Psr-4标准获取目录下的所有类
|
||||
* @param $dir
|
||||
* @param $base_namespace
|
||||
* @param null|mixed $rule
|
||||
* @param bool $return_path_value
|
||||
* @return String[]
|
||||
* @param null|mixed $rule
|
||||
* @param bool $return_path_value
|
||||
* @return string[]
|
||||
*/
|
||||
public static function getClassesPsr4($dir, $base_namespace, $rule = null, $return_path_value = false): array {
|
||||
public static function getClassesPsr4($dir, $base_namespace, $rule = null, $return_path_value = false): array
|
||||
{
|
||||
// 预先读取下composer的file列表
|
||||
$composer = json_decode(file_get_contents(DataProvider::getSourceRootDir() . '/composer.json'), true);
|
||||
$classes = [];
|
||||
@@ -85,16 +93,30 @@ class ZMUtil
|
||||
$pathinfo = pathinfo($v);
|
||||
if (($pathinfo['extension'] ?? '') == 'php') {
|
||||
if ($rule === null) { //规则未设置回调时候,使用默认的识别过滤规则
|
||||
if (substr(file_get_contents($dir . '/' . $v), 6, 6) == '#plain') continue;
|
||||
elseif (mb_substr($pathinfo["basename"], 0, 7) == 'global_' || mb_substr($pathinfo["basename"], 0, 7) == 'script_') continue;
|
||||
foreach (($composer['autoload']['files'] ?? []) as $fi) {
|
||||
if (md5_file(DataProvider::getSourceRootDir().'/'.$fi) == md5_file($dir.'/'.$v)) continue 2;
|
||||
/*if (substr(file_get_contents($dir . '/' . $v), 6, 6) == '#plain') {
|
||||
continue;
|
||||
}*/
|
||||
if (file_exists($dir . '/' . $pathinfo['basename'] . '.plain')) {
|
||||
continue;
|
||||
}
|
||||
} elseif (is_callable($rule) && !($rule($dir, $pathinfo))) continue;
|
||||
if (mb_substr($pathinfo['basename'], 0, 7) == 'global_' || mb_substr($pathinfo['basename'], 0, 7) == 'script_') {
|
||||
continue;
|
||||
}
|
||||
foreach (($composer['autoload']['files'] ?? []) as $fi) {
|
||||
if (md5_file(DataProvider::getSourceRootDir() . '/' . $fi) == md5_file($dir . '/' . $v)) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
} elseif (is_callable($rule) && !($rule($dir, $pathinfo))) {
|
||||
continue;
|
||||
}
|
||||
$dirname = $pathinfo['dirname'] == '.' ? '' : (str_replace('/', '\\', $pathinfo['dirname']) . '\\');
|
||||
$class_name = $base_namespace . '\\' . $dirname . $pathinfo['filename'];
|
||||
if (is_string($return_path_value)) $classes[$class_name] = $return_path_value . "/" .$v;
|
||||
else $classes[] = $class_name;
|
||||
if (is_string($return_path_value)) {
|
||||
$classes[$class_name] = $return_path_value . '/' . $v;
|
||||
} else {
|
||||
$classes[] = $class_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $classes;
|
||||
|
||||
Reference in New Issue
Block a user