mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-20 15:15:35 +08:00
add cs fixer and PHPStan and activate it (build 436)
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Module;
|
||||
|
||||
/**
|
||||
@@ -7,12 +9,15 @@ namespace ZM\Module;
|
||||
*/
|
||||
class InstantModule extends ModuleBase
|
||||
{
|
||||
public function onEvent($event_class, $params, callable $callable) {
|
||||
public function onEvent($event_class, $params, callable $callable)
|
||||
{
|
||||
$class = new $event_class();
|
||||
foreach ($params as $k => $v) {
|
||||
if (is_string($k)) $class->$k = $v;
|
||||
if (is_string($k)) {
|
||||
$class->{$k} = $v;
|
||||
}
|
||||
}
|
||||
$class->method = $callable;
|
||||
$this->events[] = $class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Module;
|
||||
|
||||
/**
|
||||
@@ -11,21 +13,21 @@ abstract class ModuleBase
|
||||
|
||||
protected $events = [];
|
||||
|
||||
public function __construct($module_name) {
|
||||
public function __construct($module_name)
|
||||
{
|
||||
$this->module_name = $module_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getModuleName() {
|
||||
public function getModuleName()
|
||||
{
|
||||
return $this->module_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getEvents(): array {
|
||||
public function getEvents(): array
|
||||
{
|
||||
return $this->events;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Module;
|
||||
|
||||
@@ -16,29 +17,35 @@ use ZM\Utils\ZMUtil;
|
||||
/**
|
||||
* 模块构造器
|
||||
* Class ModulePacker
|
||||
* @package ZM\Module
|
||||
* @since 2.5
|
||||
*/
|
||||
class ModulePacker
|
||||
{
|
||||
const ZM_MODULE_PACKER_VERSION = '1.0';
|
||||
/** @var array $module */
|
||||
public const ZM_MODULE_PACKER_VERSION = '1.0';
|
||||
|
||||
/** @var array */
|
||||
private $module = [];
|
||||
/** @var bool $override */
|
||||
|
||||
/** @var bool */
|
||||
private $override = false;
|
||||
/** @var string $output_path */
|
||||
|
||||
/** @var string */
|
||||
private $output_path = '';
|
||||
/** @var string $filename */
|
||||
|
||||
/** @var string */
|
||||
private $filename = '';
|
||||
/** @var Phar $phar */
|
||||
|
||||
/** @var Phar */
|
||||
private $phar;
|
||||
/** @var null|array $module_config */
|
||||
private $module_config = null;
|
||||
|
||||
/** @var null|array */
|
||||
private $module_config;
|
||||
|
||||
/**
|
||||
* @throws ModulePackException
|
||||
*/
|
||||
public function __construct(array $module) {
|
||||
public function __construct(array $module)
|
||||
{
|
||||
if (ini_get('phar.readonly') == '1') {
|
||||
throw new ModulePackException('请先在 php.ini 中设置 `phar.readonly = Off` 后再打包模块!');
|
||||
}
|
||||
@@ -52,16 +59,19 @@ class ModulePacker
|
||||
* 设置输出文件夹
|
||||
* @param $path
|
||||
*/
|
||||
public function setOutputPath($path) {
|
||||
public function setOutputPath($path)
|
||||
{
|
||||
$this->output_path = $path;
|
||||
if (!is_dir($path)) mkdir($path, 0755, true);
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path, 0755, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否覆盖
|
||||
* @param bool $override
|
||||
*/
|
||||
public function setOverride(bool $override = true) {
|
||||
public function setOverride(bool $override = true)
|
||||
{
|
||||
$this->override = $override;
|
||||
}
|
||||
|
||||
@@ -69,15 +79,16 @@ class ModulePacker
|
||||
* 获取模块名字
|
||||
* @return mixed
|
||||
*/
|
||||
public function getName() {
|
||||
public function getName()
|
||||
{
|
||||
return $this->module['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取打包的文件名绝对路径
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName(): string {
|
||||
public function getFileName(): string
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
@@ -85,7 +96,8 @@ class ModulePacker
|
||||
* 打包模块
|
||||
* @throws ZMException
|
||||
*/
|
||||
public function pack() {
|
||||
public function pack()
|
||||
{
|
||||
$this->filename = $this->output_path . '/' . $this->module['name'];
|
||||
if (isset($this->module['version'])) {
|
||||
$this->filename .= '_' . $this->module['version'];
|
||||
@@ -111,28 +123,32 @@ class ModulePacker
|
||||
$this->phar->stopBuffering();
|
||||
}
|
||||
|
||||
private function addFiles() {
|
||||
private function addFiles()
|
||||
{
|
||||
$file_list = DataProvider::scanDirFiles($this->module['module-path'], true, false);
|
||||
foreach ($file_list as $v) {
|
||||
$this->phar->addFile($v, $this->getRelativePath($v));
|
||||
}
|
||||
}
|
||||
|
||||
private function getRelativePath($path) {
|
||||
private function getRelativePath($path)
|
||||
{
|
||||
return str_replace(realpath(DataProvider::getSourceRootDir()) . '/', '', realpath($path));
|
||||
}
|
||||
|
||||
private function generatePharAutoload(): array {
|
||||
$pos = strpos($this->module['module-path'], DataProvider::getSourceRootDir().'/');
|
||||
private function generatePharAutoload(): array
|
||||
{
|
||||
$pos = strpos($this->module['module-path'], DataProvider::getSourceRootDir() . '/');
|
||||
if ($pos === 0) {
|
||||
$path_value = substr($this->module['module-path'], strlen(DataProvider::getSourceRootDir().'/'));
|
||||
$path_value = substr($this->module['module-path'], strlen(DataProvider::getSourceRootDir() . '/'));
|
||||
} else {
|
||||
throw new ModulePackException(zm_internal_errcode("E99999")); //未定义的错误
|
||||
throw new ModulePackException(zm_internal_errcode('E99999')); //未定义的错误
|
||||
}
|
||||
return ZMUtil::getClassesPsr4($this->module['module-path'], $this->module['namespace'], null, $path_value);
|
||||
}
|
||||
|
||||
private function getComposerAutoloadItems(): array {
|
||||
private function getComposerAutoloadItems(): array
|
||||
{
|
||||
$composer = json_decode(file_get_contents(DataProvider::getSourceRootDir() . '/composer.json'), true);
|
||||
$path = self::getRelativePath($this->module['module-path']);
|
||||
$item = [];
|
||||
@@ -153,21 +169,22 @@ class ModulePacker
|
||||
* @throws ZMException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function addLightCacheStore() {
|
||||
private function addLightCacheStore()
|
||||
{
|
||||
if (isset($this->module['light-cache-store'])) {
|
||||
$store = [];
|
||||
$r = ZMConfig::get('global', 'light_cache') ?? [
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900
|
||||
];
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900,
|
||||
];
|
||||
LightCache::init($r);
|
||||
foreach ($this->module['light-cache-store'] as $v) {
|
||||
$r = LightCache::get($v);
|
||||
if ($r === null) {
|
||||
Console::warning(zm_internal_errcode("E00045") . 'LightCache 项:' . $v . ' 不存在或值为null,无法为其保存。');
|
||||
Console::warning(zm_internal_errcode('E00045') . 'LightCache 项:' . $v . ' 不存在或值为null,无法为其保存。');
|
||||
} else {
|
||||
$store[$v] = $r;
|
||||
Console::info('打包LightCache持久化项:' . $v);
|
||||
@@ -177,7 +194,8 @@ class ModulePacker
|
||||
}
|
||||
}
|
||||
|
||||
private function addModuleConfig() {
|
||||
private function addModuleConfig()
|
||||
{
|
||||
$stub_values = [
|
||||
'zm-module' => true,
|
||||
'generated-id' => sha1(strval(microtime(true))),
|
||||
@@ -187,18 +205,19 @@ class ModulePacker
|
||||
'autoload-psr-4' => $this->generatePharAutoload(),
|
||||
'unpack' => [
|
||||
'composer-autoload-items' => $this->getComposerAutoloadItems(),
|
||||
'global-config-override' => $this->module['global-config-override'] ?? false
|
||||
'global-config-override' => $this->module['global-config-override'] ?? false,
|
||||
],
|
||||
'allow-hotload' => $this->module["allow-hotload"] ?? false,
|
||||
'pack-time' => time()
|
||||
'allow-hotload' => $this->module['allow-hotload'] ?? false,
|
||||
'pack-time' => time(),
|
||||
];
|
||||
$this->phar->addFromString('zmplugin.json', json_encode($stub_values, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
$this->module_config = $stub_values;
|
||||
}
|
||||
|
||||
private function addEntry() {
|
||||
private function addEntry()
|
||||
{
|
||||
$stub_replace = [
|
||||
'generated_id' => $this->module_config['generated-id']
|
||||
'generated_id' => $this->module_config['generated-id'],
|
||||
];
|
||||
|
||||
$stub_template = str_replace(
|
||||
@@ -216,24 +235,25 @@ class ModulePacker
|
||||
/**
|
||||
* @throws ModulePackException
|
||||
*/
|
||||
private function addZMDataFiles() {
|
||||
private function addZMDataFiles()
|
||||
{
|
||||
$base_dir = realpath(DataProvider::getDataFolder());
|
||||
if (is_array($this->module["zm-data-store"] ?? null)) {
|
||||
foreach ($this->module["zm-data-store"] as $v) {
|
||||
if (is_array($this->module['zm-data-store'] ?? null)) {
|
||||
foreach ($this->module['zm-data-store'] as $v) {
|
||||
if (is_dir($base_dir . '/' . $v)) {
|
||||
$v = rtrim($v, '/');
|
||||
Console::info("Adding external zm_data dir: " . $v);
|
||||
Console::info('Adding external zm_data dir: ' . $v);
|
||||
$files = DataProvider::scanDirFiles($base_dir . '/' . $v, true, true);
|
||||
foreach ($files as $single) {
|
||||
$this->phar->addFile($base_dir . '/' . $v . '/' . $single, 'zm_data/' . $v . '/' . $single);
|
||||
}
|
||||
} elseif (is_file($base_dir . '/' . $v)) {
|
||||
Console::info("Add external zm_data file: " . $v);
|
||||
Console::info('Add external zm_data file: ' . $v);
|
||||
$this->phar->addFile($base_dir . '/' . $v, 'zm_data/' . $v);
|
||||
} else {
|
||||
throw new ModulePackException(zm_internal_errcode("E00066")."`zmdata-store` 指定的文件或目录不存在");
|
||||
throw new ModulePackException(zm_internal_errcode('E00066') . '`zmdata-store` 指定的文件或目录不存在');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Module;
|
||||
|
||||
|
||||
use Jelix\Version\VersionComparator;
|
||||
use ZM\Config\ZMConfig;
|
||||
use ZM\Console\Console;
|
||||
@@ -17,27 +17,25 @@ class ModuleUnpacker
|
||||
{
|
||||
private $module;
|
||||
|
||||
private $module_config = null;
|
||||
private $module_config;
|
||||
|
||||
private $light_cache = null;
|
||||
private $light_cache;
|
||||
|
||||
private $unpack_data_files = [];
|
||||
|
||||
public function __construct(array $module) {
|
||||
public function __construct(array $module)
|
||||
{
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解包模块
|
||||
* @param bool $override_light_cache
|
||||
* @param bool $override_data_files
|
||||
* @param bool $override_source
|
||||
* @param bool $ignore_depends
|
||||
* @return array
|
||||
* @param bool $ignore_depends
|
||||
* @throws ModulePackException
|
||||
* @throws ZMException
|
||||
*/
|
||||
public function unpack(bool $override_light_cache = false, bool $override_data_files = false, bool $override_source = false, $ignore_depends = false): array {
|
||||
public function unpack(bool $override_light_cache = false, bool $override_data_files = false, bool $override_source = false, $ignore_depends = false): array
|
||||
{
|
||||
$this->checkConfig();
|
||||
$this->checkDepends($ignore_depends);
|
||||
$this->checkLightCacheStore();
|
||||
@@ -54,29 +52,30 @@ class ModuleUnpacker
|
||||
|
||||
/**
|
||||
* 检查模块配置文件是否正确地放在phar包的位置中
|
||||
* @return void
|
||||
*/
|
||||
private function checkConfig() {
|
||||
$config = "phar://" . $this->module["phar-path"] . "/" . $this->module["module-root-path"] . "/zm.json";
|
||||
private function checkConfig()
|
||||
{
|
||||
$config = 'phar://' . $this->module['phar-path'] . '/' . $this->module['module-root-path'] . '/zm.json';
|
||||
$this->module_config = json_decode(file_get_contents($config), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查模块依赖关系
|
||||
* @param bool $ignore_depends
|
||||
* @param bool $ignore_depends
|
||||
* @throws ModulePackException
|
||||
* @throws ZMException
|
||||
*/
|
||||
private function checkDepends($ignore_depends = false) {
|
||||
private function checkDepends($ignore_depends = false)
|
||||
{
|
||||
$configured = ModuleManager::getConfiguredModules();
|
||||
$depends = $this->module_config["depends"] ?? [];
|
||||
$depends = $this->module_config['depends'] ?? [];
|
||||
foreach ($depends as $k => $v) {
|
||||
if (!isset($configured[$k]) && !$ignore_depends) {
|
||||
throw new ModulePackException(zm_internal_errcode("E00064") . "模块 " . $this->module_config["name"] . " 依赖的模块 $k 不存在");
|
||||
throw new ModulePackException(zm_internal_errcode('E00064') . '模块 ' . $this->module_config['name'] . " 依赖的模块 {$k} 不存在");
|
||||
}
|
||||
$current_ver = $configured[$k]["version"] ?? "1.0";
|
||||
$current_ver = $configured[$k]['version'] ?? '1.0';
|
||||
if (!VersionComparator::compareVersionRange($current_ver, $v) && !$ignore_depends) {
|
||||
throw new ModulePackException(zm_internal_errcode("E00063") . "模块 " . $this->module_config["name"] . " 依赖的模块 $k 版本依赖不符合条件(现有版本: " . $current_ver . ", 需求版本: " . $v . ")");
|
||||
throw new ModulePackException(zm_internal_errcode('E00063') . '模块 ' . $this->module_config['name'] . " 依赖的模块 {$k} 版本依赖不符合条件(现有版本: " . $current_ver . ', 需求版本: ' . $v . ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,10 +84,13 @@ class ModuleUnpacker
|
||||
* 检查 light-cache-store 项是否合规
|
||||
* @throws ModulePackException
|
||||
*/
|
||||
private function checkLightCacheStore() {
|
||||
if (isset($this->module_config["light-cache-store"])) {
|
||||
$file = json_decode(file_get_contents("phar://" . $this->module["phar-path"] . "/light_cache_store.json"), true);
|
||||
if ($file === null) throw new ModulePackException(zm_internal_errcode("E00065") . "模块系统检测到打包的模块文件中未含有 `light_cache_store.json` 文件");
|
||||
private function checkLightCacheStore()
|
||||
{
|
||||
if (isset($this->module_config['light-cache-store'])) {
|
||||
$file = json_decode(file_get_contents('phar://' . $this->module['phar-path'] . '/light_cache_store.json'), true);
|
||||
if ($file === null) {
|
||||
throw new ModulePackException(zm_internal_errcode('E00065') . '模块系统检测到打包的模块文件中未含有 `light_cache_store.json` 文件');
|
||||
}
|
||||
$this->light_cache = $file;
|
||||
}
|
||||
}
|
||||
@@ -96,17 +98,18 @@ class ModuleUnpacker
|
||||
/**
|
||||
* @throws ModulePackException
|
||||
*/
|
||||
private function checkZMDataStore() {
|
||||
if (is_array($this->module_config["zm-data-store"] ?? null)) {
|
||||
foreach ($this->module_config["zm-data-store"] as $v) {
|
||||
if (!file_exists("phar://" . $this->module["phar-path"] . "/zm_data/" . $v)) {
|
||||
throw new ModulePackException(zm_internal_errcode("E00067") . "压缩包损坏,内部找不到待解压的 zm_data 原始数据");
|
||||
private function checkZMDataStore()
|
||||
{
|
||||
if (is_array($this->module_config['zm-data-store'] ?? null)) {
|
||||
foreach ($this->module_config['zm-data-store'] as $v) {
|
||||
if (!file_exists('phar://' . $this->module['phar-path'] . '/zm_data/' . $v)) {
|
||||
throw new ModulePackException(zm_internal_errcode('E00067') . '压缩包损坏,内部找不到待解压的 zm_data 原始数据');
|
||||
}
|
||||
$file = "phar://" . $this->module["phar-path"] . "/zm_data/" . $v;
|
||||
$file = 'phar://' . $this->module['phar-path'] . '/zm_data/' . $v;
|
||||
if (is_dir($file)) {
|
||||
$all = DataProvider::scanDirFiles($file, true, true);
|
||||
foreach ($all as $single) {
|
||||
$this->unpack_data_files[$file . "/" . $single] = DataProvider::getDataFolder() . $v . "/" . $single;
|
||||
$this->unpack_data_files[$file . '/' . $single] = DataProvider::getDataFolder() . $v . '/' . $single;
|
||||
}
|
||||
} else {
|
||||
$this->unpack_data_files[$file] = DataProvider::getDataFolder() . $v;
|
||||
@@ -115,105 +118,119 @@ class ModuleUnpacker
|
||||
}
|
||||
}
|
||||
|
||||
private function mergeComposer() {
|
||||
$composer_file = DataProvider::getWorkingDir() . "/composer.json";
|
||||
if (!file_exists($composer_file)) throw new ModulePackException(zm_internal_errcode("E00068"));
|
||||
private function mergeComposer()
|
||||
{
|
||||
$composer_file = DataProvider::getWorkingDir() . '/composer.json';
|
||||
if (!file_exists($composer_file)) {
|
||||
throw new ModulePackException(zm_internal_errcode('E00068'));
|
||||
}
|
||||
$composer = json_decode(file_get_contents($composer_file), true);
|
||||
if (isset($this->module_config["composer-extend-autoload"])) {
|
||||
$autoload = $this->module_config["composer-extend-autoload"];
|
||||
if (isset($autoload["psr-4"])) {
|
||||
Console::info("Adding extended autoload psr-4 for composer");
|
||||
$composer["autoload"]["psr-4"] = isset($composer["autoload"]["psr-4"]) ? array_merge($composer["autoload"]["psr-4"], $autoload["psr-4"]) : $autoload["psr-4"];
|
||||
if (isset($this->module_config['composer-extend-autoload'])) {
|
||||
$autoload = $this->module_config['composer-extend-autoload'];
|
||||
if (isset($autoload['psr-4'])) {
|
||||
Console::info('Adding extended autoload psr-4 for composer');
|
||||
$composer['autoload']['psr-4'] = isset($composer['autoload']['psr-4']) ? array_merge($composer['autoload']['psr-4'], $autoload['psr-4']) : $autoload['psr-4'];
|
||||
}
|
||||
if (isset($autoload["files"])) {
|
||||
Console::info("Adding extended autoload file for composer");
|
||||
$composer["autoload"]["files"] = isset($composer["autoload"]["files"]) ? array_merge($composer["autoload"]["files"], $autoload["files"]) : $autoload["files"];
|
||||
if (isset($autoload['files'])) {
|
||||
Console::info('Adding extended autoload file for composer');
|
||||
$composer['autoload']['files'] = isset($composer['autoload']['files']) ? array_merge($composer['autoload']['files'], $autoload['files']) : $autoload['files'];
|
||||
}
|
||||
}
|
||||
if (isset($this->module_config["composer-extend-require"])) {
|
||||
foreach ($this->module_config["composer-extend-require"] as $k => $v) {
|
||||
Console::info("Adding extended required composer library: " . $k);
|
||||
if (!isset($composer[$k])) $composer[$k] = $v;
|
||||
if (isset($this->module_config['composer-extend-require'])) {
|
||||
foreach ($this->module_config['composer-extend-require'] as $k => $v) {
|
||||
Console::info('Adding extended required composer library: ' . $k);
|
||||
if (!isset($composer[$k])) {
|
||||
$composer[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
file_put_contents($composer_file, json_encode($composer, 64 | 128 | 256));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $override_data
|
||||
* @throws ModulePackException
|
||||
*/
|
||||
private function copyZMDataStore($override_data) {
|
||||
private function copyZMDataStore($override_data)
|
||||
{
|
||||
foreach ($this->unpack_data_files as $k => $v) {
|
||||
$pathinfo = pathinfo($v);
|
||||
if (!is_dir($pathinfo["dirname"])) @mkdir($pathinfo["dirname"], 0755, true);
|
||||
if (!is_dir($pathinfo['dirname'])) {
|
||||
@mkdir($pathinfo['dirname'], 0755, true);
|
||||
}
|
||||
if (is_file($v) && $override_data !== true) {
|
||||
Console::info("Skipping zm_data file (not overwriting): " . $v);
|
||||
Console::info('Skipping zm_data file (not overwriting): ' . $v);
|
||||
continue;
|
||||
}
|
||||
Console::info("Copying zm_data file: " . $v);
|
||||
Console::info('Copying zm_data file: ' . $v);
|
||||
if (copy($k, $v) !== true) {
|
||||
throw new ModulePackException(zm_internal_errcode("E00068") . "Cannot copy file: " . $v);
|
||||
throw new ModulePackException(zm_internal_errcode('E00068') . 'Cannot copy file: ' . $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function copyLightCacheStore($override) {
|
||||
private function copyLightCacheStore($override)
|
||||
{
|
||||
$r = ZMConfig::get('global', 'light_cache') ?? [
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900
|
||||
];
|
||||
'size' => 512, //最多允许储存的条数(需要2的倍数)
|
||||
'max_strlen' => 32768, //单行字符串最大长度(需要2的倍数)
|
||||
'hash_conflict_proportion' => 0.6, //Hash冲突率(越大越好,但是需要的内存更多)
|
||||
'persistence_path' => DataProvider::getDataFolder() . '_cache.json',
|
||||
'auto_save_interval' => 900,
|
||||
];
|
||||
LightCache::init($r);
|
||||
foreach (($this->light_cache ?? []) as $k => $v) {
|
||||
if (LightCache::isset($k) && $override !== true) continue;
|
||||
if (LightCache::isset($k) && $override !== true) {
|
||||
continue;
|
||||
}
|
||||
LightCache::addPersistence($k);
|
||||
LightCache::set($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
private function mergeGlobalConfig() {
|
||||
if ($this->module["unpack"]["global-config-override"] !== false) {
|
||||
$prompt = !is_string($this->module["unpack"]["global-config-override"]) ? "请根据模块提供者提供的要求进行修改 global.php 中对应的配置项" : $this->module["unpack"]["global-config-override"];
|
||||
Console::warning("模块作者要求用户手动修改 global.php 配置文件中的项目:");
|
||||
Console::warning("*" . $prompt);
|
||||
echo Console::setColor("请输入修改模式,y(使用vim修改)/e(自行使用其他编辑器修改后确认)/N(默认暂不修改):[y/e/N] ", "gold");
|
||||
private function mergeGlobalConfig()
|
||||
{
|
||||
if ($this->module['unpack']['global-config-override'] !== false) {
|
||||
$prompt = !is_string($this->module['unpack']['global-config-override']) ? '请根据模块提供者提供的要求进行修改 global.php 中对应的配置项' : $this->module['unpack']['global-config-override'];
|
||||
Console::warning('模块作者要求用户手动修改 global.php 配置文件中的项目:');
|
||||
Console::warning('*' . $prompt);
|
||||
echo Console::setColor('请输入修改模式,y(使用vim修改)/e(自行使用其他编辑器修改后确认)/N(默认暂不修改):[y/e/N] ', 'gold');
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
switch ($r) {
|
||||
case "y":
|
||||
system("vim " . escapeshellarg(DataProvider::getWorkingDir() . "/config/global.php") . " > `tty`");
|
||||
Console::info("已使用 vim 修改!");
|
||||
case 'y':
|
||||
system('vim ' . escapeshellarg(DataProvider::getWorkingDir() . '/config/global.php') . ' > `tty`');
|
||||
Console::info('已使用 vim 修改!');
|
||||
break;
|
||||
case "e":
|
||||
echo Console::setColor("请修改后文件点击回车即可继续 [Enter] ", "gold");
|
||||
case 'e':
|
||||
echo Console::setColor('请修改后文件点击回车即可继续 [Enter] ', 'gold');
|
||||
fgets(STDIN);
|
||||
break;
|
||||
case "n":
|
||||
Console::info("暂不修改 global.php");
|
||||
case 'n':
|
||||
Console::info('暂不修改 global.php');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function copySource(bool $override_source) {
|
||||
$origin_base = "phar://" . $this->module["phar-path"] . "/" . $this->module["module-root-path"];
|
||||
private function copySource(bool $override_source)
|
||||
{
|
||||
$origin_base = 'phar://' . $this->module['phar-path'] . '/' . $this->module['module-root-path'];
|
||||
$dir = DataProvider::scanDirFiles($origin_base, true, true);
|
||||
$base = DataProvider::getSourceRootDir() . "/" . $this->module["module-root-path"];
|
||||
$base = DataProvider::getSourceRootDir() . '/' . $this->module['module-root-path'];
|
||||
foreach ($dir as $v) {
|
||||
$info = pathinfo($base . "/" . $v);
|
||||
if (!is_dir($info["dirname"])) {
|
||||
@mkdir($info["dirname"], 0755, true);
|
||||
$info = pathinfo($base . '/' . $v);
|
||||
if (!is_dir($info['dirname'])) {
|
||||
@mkdir($info['dirname'], 0755, true);
|
||||
}
|
||||
if (is_file($base . "/" . $v) && $override_source !== true) {
|
||||
Console::info("Skipping source file (not overwriting): " . $v);
|
||||
if (is_file($base . '/' . $v) && $override_source !== true) {
|
||||
Console::info('Skipping source file (not overwriting): ' . $v);
|
||||
continue;
|
||||
}
|
||||
Console::info("Releasing source file: " . $this->module["module-root-path"] . "/" . $v);
|
||||
Console::info('Releasing source file: ' . $this->module['module-root-path'] . '/' . $v);
|
||||
|
||||
if (copy($origin_base . "/" . $v, $base . "/" . $v) !== true) {
|
||||
throw new ModulePackException(zm_internal_errcode("E00068") . "Cannot copy file: " . $v);
|
||||
if (copy($origin_base . '/' . $v, $base . '/' . $v) !== true) {
|
||||
throw new ModulePackException(zm_internal_errcode('E00068') . 'Cannot copy file: ' . $v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ZM\Module;
|
||||
|
||||
@@ -22,60 +23,78 @@ use ZM\Utils\SingletonTrait;
|
||||
|
||||
/**
|
||||
* Class QQBot
|
||||
* @package ZM\Module
|
||||
*/
|
||||
class QQBot
|
||||
{
|
||||
use SingletonTrait;
|
||||
|
||||
public function handleByEvent() {
|
||||
public function handleByEvent()
|
||||
{
|
||||
$data = json_decode(context()->getFrame()->data, true);
|
||||
$this->handle($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param int $level
|
||||
* @param int $level
|
||||
* @throws InterruptException
|
||||
*/
|
||||
public function handle($data, $level = 0) {
|
||||
public function handle($data, $level = 0)
|
||||
{
|
||||
try {
|
||||
if ($level > 10) return;
|
||||
set_coroutine_params(["data" => $data]);
|
||||
if (isset($data["post_type"])) {
|
||||
if ($level > 10) {
|
||||
return;
|
||||
}
|
||||
set_coroutine_params(['data' => $data]);
|
||||
if (isset($data['post_type'])) {
|
||||
//echo TermColor::ITALIC.json_encode($data, 128|256).TermColor::RESET.PHP_EOL;
|
||||
ctx()->setCache("level", $level);
|
||||
ctx()->setCache('level', $level);
|
||||
//Console::debug("Calling CQ Event from fd=" . ctx()->getConnection()->getFd());
|
||||
if ($data["post_type"] != "meta_event") {
|
||||
$r = $this->dispatchBeforeEvents($data, "pre"); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === "block") EventDispatcher::interrupt();
|
||||
if ($data['post_type'] != 'meta_event') {
|
||||
$r = $this->dispatchBeforeEvents($data, 'pre'); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === 'block') {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
//Console::warning("最上数据包:".json_encode($data));
|
||||
}
|
||||
if (isset($data["echo"]) || isset($data["post_type"])) {
|
||||
if (CoMessage::resumeByWS()) EventDispatcher::interrupt();
|
||||
if (isset($data['echo']) || isset($data['post_type'])) {
|
||||
if (CoMessage::resumeByWS()) {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
if (($data["post_type"] ?? "meta_event") != "meta_event") {
|
||||
$r = $this->dispatchBeforeEvents($data, "post"); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === "block") EventDispatcher::interrupt();
|
||||
if (($data['post_type'] ?? 'meta_event') != 'meta_event') {
|
||||
$r = $this->dispatchBeforeEvents($data, 'post'); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === 'block') {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
if (isset($data['post_type'])) {
|
||||
$this->dispatchEvents($data);
|
||||
} else {
|
||||
$this->dispatchAPIResponse($data);
|
||||
}
|
||||
if (isset($data["post_type"])) $this->dispatchEvents($data);
|
||||
else $this->dispatchAPIResponse($data);
|
||||
|
||||
if (($data["post_type"] ?? "meta_event") != "meta_event") {
|
||||
if (($data['post_type'] ?? 'meta_event') != 'meta_event') {
|
||||
$r = $this->dispatchAfterEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === "block") EventDispatcher::interrupt();
|
||||
if ($r->store === 'block') {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
} /** @noinspection PhpRedundantCatchClauseInspection */ catch (WaitTimeoutException $e) {
|
||||
if (($data["post_type"] ?? "meta_event") != "meta_event") {
|
||||
} /* @noinspection PhpRedundantCatchClauseInspection */ catch (WaitTimeoutException $e) {
|
||||
if (($data['post_type'] ?? 'meta_event') != 'meta_event') {
|
||||
$r = $this->dispatchAfterEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === "block") EventDispatcher::interrupt();
|
||||
if ($r->store === 'block') {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
$e->module->finalReply($e->getMessage());
|
||||
} catch (InterruptException $e) {
|
||||
if (($data["post_type"] ?? "meta_event") != "meta_event") {
|
||||
if (($data['post_type'] ?? 'meta_event') != 'meta_event') {
|
||||
$r = $this->dispatchAfterEvents($data); // before在这里执行,元事件不执行before为减少不必要的调试日志
|
||||
if ($r->store === "block") EventDispatcher::interrupt();
|
||||
if ($r->store === 'block') {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
@@ -85,22 +104,24 @@ class QQBot
|
||||
/**
|
||||
* @param $data
|
||||
* @param $time
|
||||
* @return EventDispatcher
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatchBeforeEvents($data, $time): EventDispatcher {
|
||||
public function dispatchBeforeEvents($data, $time): EventDispatcher
|
||||
{
|
||||
$before = new EventDispatcher(CQBefore::class);
|
||||
if ($time === "pre") {
|
||||
if ($time === 'pre') {
|
||||
$before->setRuleFunction(function ($v) use ($data) {
|
||||
return $v->level >= 200 && $v->cq_event == $data["post_type"];
|
||||
return $v->level >= 200 && $v->cq_event == $data['post_type'];
|
||||
});
|
||||
} else {
|
||||
$before->setRuleFunction(function ($v) use ($data) {
|
||||
return $v->level < 200 && $v->cq_event == $data["post_type"];
|
||||
return $v->level < 200 && $v->cq_event == $data['post_type'];
|
||||
});
|
||||
}
|
||||
$before->setReturnFunction(function ($result) {
|
||||
if (!$result) EventDispatcher::interrupt("block");
|
||||
if (!$result) {
|
||||
EventDispatcher::interrupt('block');
|
||||
}
|
||||
});
|
||||
$before->dispatchEvents($data);
|
||||
return $before;
|
||||
@@ -111,23 +132,32 @@ class QQBot
|
||||
* @throws InterruptException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function dispatchEvents($data) {
|
||||
private function dispatchEvents($data)
|
||||
{
|
||||
//Console::warning("最xia数据包:".json_encode($data));
|
||||
switch ($data["post_type"]) {
|
||||
case "message":
|
||||
switch ($data['post_type']) {
|
||||
case 'message':
|
||||
//分发CQCommand事件
|
||||
$dispatcher = new EventDispatcher(CQCommand::class);
|
||||
$dispatcher->setReturnFunction(function ($result) {
|
||||
if (is_string($result)) ctx()->reply($result);
|
||||
if (ctx()->getCache("has_reply") === true) EventDispatcher::interrupt();
|
||||
if (is_string($result)) {
|
||||
ctx()->reply($result);
|
||||
}
|
||||
if (ctx()->getCache('has_reply') === true) {
|
||||
EventDispatcher::interrupt();
|
||||
}
|
||||
});
|
||||
$s = MessageUtil::matchCommand(ctx()->getStringMessage(), ctx()->getData());
|
||||
if ($s->status !== false) {
|
||||
if (!empty($s->match)) ctx()->setCache("match", $s->match);
|
||||
if (!empty($s->match)) {
|
||||
ctx()->setCache('match', $s->match);
|
||||
}
|
||||
$dispatcher->dispatchEvent($s->object, null);
|
||||
if (is_string($dispatcher->store)) ctx()->reply($dispatcher->store);
|
||||
if (ctx()->getCache("has_reply") === true) {
|
||||
$policy = ZMConfig::get("global", "onebot")['message_command_policy'] ?? 'interrupt';
|
||||
if (is_string($dispatcher->store)) {
|
||||
ctx()->reply($dispatcher->store);
|
||||
}
|
||||
if (ctx()->getCache('has_reply') === true) {
|
||||
$policy = ZMConfig::get('global', 'onebot')['message_command_policy'] ?? 'interrupt';
|
||||
switch ($policy) {
|
||||
case 'interrupt':
|
||||
EventDispatcher::interrupt();
|
||||
@@ -135,7 +165,7 @@ class QQBot
|
||||
case 'continue':
|
||||
break;
|
||||
default:
|
||||
throw new Exception("未知的消息命令策略:" . $policy);
|
||||
throw new Exception('未知的消息命令策略:' . $policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,54 +173,57 @@ class QQBot
|
||||
//分发CQMessage事件
|
||||
$msg_dispatcher = new EventDispatcher(CQMessage::class);
|
||||
$msg_dispatcher->setRuleFunction(function ($v) {
|
||||
return ($v->message == '' || ($v->message == ctx()->getStringMessage())) &&
|
||||
($v->user_id == 0 || ($v->user_id == ctx()->getUserId())) &&
|
||||
($v->group_id == 0 || ($v->group_id == (ctx()->getGroupId() ?? 0))) &&
|
||||
($v->message_type == '' || ($v->message_type == ctx()->getMessageType())) &&
|
||||
($v->raw_message == '' || ($v->raw_message == context()->getData()["raw_message"]));
|
||||
return ($v->message == '' || ($v->message == ctx()->getStringMessage()))
|
||||
&& ($v->user_id == 0 || ($v->user_id == ctx()->getUserId()))
|
||||
&& ($v->group_id == 0 || ($v->group_id == (ctx()->getGroupId() ?? 0)))
|
||||
&& ($v->message_type == '' || ($v->message_type == ctx()->getMessageType()))
|
||||
&& ($v->raw_message == '' || ($v->raw_message == context()->getData()['raw_message']));
|
||||
});
|
||||
$msg_dispatcher->setReturnFunction(function ($result) {
|
||||
if (is_string($result)) ctx()->reply($result);
|
||||
if (is_string($result)) {
|
||||
ctx()->reply($result);
|
||||
}
|
||||
});
|
||||
$msg_dispatcher->dispatchEvents(ctx()->getMessage());
|
||||
return;
|
||||
case "meta_event":
|
||||
case 'meta_event':
|
||||
//Console::success("当前数据包:".json_encode(ctx()->getData()));
|
||||
$dispatcher = new EventDispatcher(CQMetaEvent::class);
|
||||
$dispatcher->setRuleFunction(function (CQMetaEvent $v) {
|
||||
return ($v->meta_event_type == '' || ($v->meta_event_type != '' && $v->meta_event_type == ctx()->getData()["meta_event_type"]));
|
||||
return $v->meta_event_type == '' || ($v->meta_event_type != '' && $v->meta_event_type == ctx()->getData()['meta_event_type']);
|
||||
});
|
||||
//eval(BP);
|
||||
$dispatcher->dispatchEvents(ctx()->getData());
|
||||
return;
|
||||
case "notice":
|
||||
case 'notice':
|
||||
$dispatcher = new EventDispatcher(CQNotice::class);
|
||||
$dispatcher->setRuleFunction(function (CQNotice $v) {
|
||||
return
|
||||
($v->notice_type == '' || ($v->notice_type != '' && $v->notice_type == ctx()->getData()["notice_type"])) &&
|
||||
($v->sub_type == '' || ($v->sub_type != '' && $v->sub_type == ctx()->getData()["sub_type"])) &&
|
||||
($v->group_id == '' || ($v->group_id != '' && $v->group_id == ctx()->getData()["group_id"])) &&
|
||||
($v->operator_id == '' || ($v->operator_id != '' && $v->operator_id == ctx()->getData()["operator_id"]));
|
||||
($v->notice_type == '' || ($v->notice_type != '' && $v->notice_type == ctx()->getData()['notice_type']))
|
||||
&& ($v->sub_type == '' || ($v->sub_type != '' && $v->sub_type == ctx()->getData()['sub_type']))
|
||||
&& ($v->group_id == '' || ($v->group_id != '' && $v->group_id == ctx()->getData()['group_id']))
|
||||
&& ($v->operator_id == '' || ($v->operator_id != '' && $v->operator_id == ctx()->getData()['operator_id']));
|
||||
});
|
||||
$dispatcher->dispatchEvents(ctx()->getData());
|
||||
return;
|
||||
case "request":
|
||||
case 'request':
|
||||
$dispatcher = new EventDispatcher(CQRequest::class);
|
||||
$dispatcher->setRuleFunction(function (CQRequest $v) {
|
||||
return ($v->request_type == '' || ($v->request_type != '' && $v->request_type == ctx()->getData()['request_type'])) &&
|
||||
($v->sub_type == '' || ($v->sub_type != '' && $v->sub_type == ctx()->getData()['sub_type'])) &&
|
||||
($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == ctx()->getData()["user_id"])) &&
|
||||
($v->comment == '' || ($v->comment != '' && $v->comment == ctx()->getData()['comment']));
|
||||
return ($v->request_type == '' || ($v->request_type != '' && $v->request_type == ctx()->getData()['request_type']))
|
||||
&& ($v->sub_type == '' || ($v->sub_type != '' && $v->sub_type == ctx()->getData()['sub_type']))
|
||||
&& ($v->user_id == 0 || ($v->user_id != 0 && $v->user_id == ctx()->getData()['user_id']))
|
||||
&& ($v->comment == '' || ($v->comment != '' && $v->comment == ctx()->getData()['comment']));
|
||||
});
|
||||
$dispatcher->dispatchEvents(ctx()->getData());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function dispatchAfterEvents($data): EventDispatcher {
|
||||
private function dispatchAfterEvents($data): EventDispatcher
|
||||
{
|
||||
$after = new EventDispatcher(CQAfter::class);
|
||||
$after->setRuleFunction(function ($v) use ($data) {
|
||||
return $v->cq_event == $data["post_type"];
|
||||
return $v->cq_event == $data['post_type'];
|
||||
});
|
||||
$after->dispatchEvents($data);
|
||||
return $after;
|
||||
@@ -200,11 +233,12 @@ class QQBot
|
||||
* @param $req
|
||||
* @throws Exception
|
||||
*/
|
||||
private function dispatchAPIResponse($req) {
|
||||
set_coroutine_params(["cq_response" => $req]);
|
||||
private function dispatchAPIResponse($req)
|
||||
{
|
||||
set_coroutine_params(['cq_response' => $req]);
|
||||
$dispatcher = new EventDispatcher(CQAPIResponse::class);
|
||||
$dispatcher->setRuleFunction(function (CQAPIResponse $response) {
|
||||
return $response->retcode == ctx()->getCQResponse()["retcode"];
|
||||
return $response->retcode == ctx()->getCQResponse()['retcode'];
|
||||
});
|
||||
$dispatcher->dispatchEvents($req);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user