update to 2.3.1 version (build 388)

cleanup code and fix a bug
This commit is contained in:
crazywhalecc 2021-03-18 14:56:35 +08:00
parent 456b102c15
commit e77b9d4970
57 changed files with 179 additions and 508 deletions

View File

@ -1,5 +0,0 @@
#!/bin/bash
if [ ! -d "/app/zhamao-framework/bin" ]; then
cp -r /app/zhamao-framework-bak/* /app/zhamao-framework/
fi
php /app/zhamao-framework/bin/start

View File

@ -1,5 +1,5 @@
#!/usr/bin/env php
<?php
/** @noinspection ALL */<?php
/**
* Copyright: Swlib
* Author: Twosee <twose@qq.com>
@ -52,6 +52,7 @@ if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
}
}
}
/** @noinspection PhpIncludeInspection */
require PHPUNIT_COMPOSER_INSTALL;
$starttime = microtime(true);
go(function (){

View File

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

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpMissingReturnTypeInspection */
namespace Module\Example;
@ -6,12 +6,12 @@ use ZM\Annotation\Http\Middleware;
use ZM\Annotation\Swoole\OnCloseEvent;
use ZM\Annotation\Swoole\OnOpenEvent;
use ZM\Annotation\Swoole\OnRequestEvent;
use ZM\Annotation\Swoole\OnStart;
use ZM\ConnectionManager\ConnectionObject;
use ZM\Console\Console;
use ZM\Annotation\CQ\CQCommand;
use ZM\Annotation\Http\RequestMapping;
use ZM\Event\EventDispatcher;
use ZM\Exception\InterruptException;
use ZM\Requests\ZMRequest;
use ZM\Utils\ZMUtil;
@ -135,6 +135,7 @@ class Hello
/**
* 阻止 Chrome 自动请求 /favicon.ico 导致的多条请求并发和干扰
* @OnRequestEvent(rule="ctx()->getRequest()->server['request_uri'] == '/favicon.ico'",level=200)
* @throws InterruptException
*/
public function onRequest() {
EventDispatcher::interrupt();

View File

@ -24,7 +24,7 @@ class TimerMiddleware implements MiddlewareInterface
* @HandleBefore()
* @return bool
*/
public function onBefore() {
public function onBefore(): bool {
$this->starttime = microtime(true);
return true;
}

View File

@ -1,4 +1,6 @@
<?php
<?php /** @noinspection PhpUnused */
/** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\API;

View File

@ -75,10 +75,11 @@ trait CQAPI
* @return bool
* @noinspection PhpUnusedParameterInspection
*/
public function processHttpAPI($connection, $reply, $function = null) {
public function processHttpAPI($connection, $reply, $function = null): bool {
return false;
}
/** @noinspection PhpMissingReturnTypeInspection */
public function __call($name, $arguments) {
return false;
}

View File

@ -1,4 +1,6 @@
<?php /** @noinspection PhpUnused */
<?php /** @noinspection PhpMissingReturnTypeInspection */
/** @noinspection PhpUnused */
namespace ZM\API;

View File

@ -12,7 +12,7 @@ abstract class AnnotationBase
public $class;
public function __toString() {
public function __toString(): string {
$str = __CLASS__ . ": ";
foreach ($this as $k => $v) {
$str .= "\n\t" . $k . " => ";

View File

@ -125,10 +125,7 @@ class AnnotationParser
Console::debug("解析注解完毕!");
}
/**
* @return array
*/
public function generateAnnotationEvents() {
public function generateAnnotationEvents(): array {
$o = [];
foreach ($this->annotation_map as $module => $obj) {
foreach (($obj["class_annotations"] ?? []) as $class_annotation) {
@ -151,17 +148,17 @@ class AnnotationParser
/**
* @return array
*/
public function getMiddlewares() { return $this->middlewares; }
public function getMiddlewares(): array { return $this->middlewares; }
/**
* @return array
*/
public function getMiddlewareMap() { return $this->middleware_map; }
public function getMiddlewareMap(): array { return $this->middleware_map; }
/**
* @return array
*/
public function getReqMapping() { return $this->req_mapping; }
public function getReqMapping(): array { return $this->req_mapping; }
/**
* @param $path
@ -171,7 +168,7 @@ class AnnotationParser
//private function below
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class) {
private function registerMiddleware(MiddlewareClass $vs, ReflectionClass $reflection_class): array {
$result = [
"class" => "\\" . $reflection_class->getName(),
"name" => $vs->name

View File

@ -26,7 +26,7 @@ class CQAfter extends AnnotationBase implements Level
/**
* @return mixed
*/
public function getLevel() {
public function getLevel(): int {
return $this->level;
}

View File

@ -28,7 +28,7 @@ class CQBefore extends AnnotationBase implements Level
/**
* @return mixed
*/
public function getLevel() {
public function getLevel(): int {
return $this->level;
}

View File

@ -32,7 +32,7 @@ class CQMessage extends AnnotationBase implements Level
/** @var int */
public $level = 20;
public function getLevel() { return $this->level; }
public function getLevel(): int { return $this->level; }
public function setLevel(int $level) {
$this->level = $level;

View File

@ -27,7 +27,7 @@ class CQMetaEvent extends AnnotationBase implements Level
/**
* @return mixed
*/
public function getLevel() { return $this->level; }
public function getLevel(): int { return $this->level; }
/**
* @param int $level

View File

@ -30,7 +30,7 @@ class OnTask extends AnnotationBase implements Rule
/**
* @return mixed
*/
public function getRule() {
public function getRule(): string {
return $this->rule;
}
}

View File

@ -26,7 +26,7 @@ class BuildCommand extends Command
// ...
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
$this->output = $output;
$target_dir = $input->getOption("target") ?? (__DIR__ . '/../../../resources/');
if (mb_strpos($target_dir, "../")) $target_dir = realpath($target_dir);

View File

@ -13,7 +13,7 @@ abstract class DaemonCommand extends Command
{
protected $daemon_file = null;
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
$pid_path = DataProvider::getWorkingDir() . "/.daemon_pid";
if (!file_exists($pid_path)) {
$output->writeln("<comment>没有检测到正在运行的守护进程!</comment>");

View File

@ -15,7 +15,7 @@ class DaemonReloadCommand extends DaemonCommand
$this->setDescription("重载守护进程下的用户代码(仅限--daemon模式可用");
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
system("kill -USR1 " . intval($this->daemon_file["pid"]));
$output->writeln("<info>成功重载!</info>");

View File

@ -15,7 +15,7 @@ class DaemonStatusCommand extends DaemonCommand
$this->setDescription("查看守护进程框架的运行状态(仅限--daemon模式可用");
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
$output->writeln("<info>框架运行中pid" . $this->daemon_file["pid"] . "</info>");
$output->writeln("<comment>----- 以下是stdout内容 -----</comment>");

View File

@ -16,7 +16,7 @@ class DaemonStopCommand extends DaemonCommand
$this->setDescription("停止守护进程下运行的框架(仅限--daemon模式可用");
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
system("kill -TERM " . intval($this->daemon_file["pid"]));
unlink(DataProvider::getWorkingDir() . "/.daemon_pid");

View File

@ -30,7 +30,7 @@ class InitCommand extends Command
// ...
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
if (LOAD_MODE === 1) { // 从composer依赖而来的项目模式最基本的需要初始化的模式
$output->writeln("<comment>Initializing files</comment>");
$base_path = LOAD_MODE_COMPOSER_PATH;
@ -96,7 +96,7 @@ class InitCommand extends Command
return Command::FAILURE;
}
private function getExtractFiles() {
private function getExtractFiles(): array {
return $this->extract_files;
}
}

View File

@ -5,7 +5,6 @@ namespace ZM\Command;
use Swoole\Atomic;
use Swoole\Coroutine;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;
@ -36,7 +35,7 @@ class PureHttpCommand extends Command
// ...
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
$tty_width = explode(" ", trim(exec("stty size")))[1];
if (realpath($input->getArgument('dir') ?? '.') === false) {
$output->writeln("<error>Directory error(" . ($input->getArgument('dir') ?? '.') . "): no such file or directory.</error>");

View File

@ -33,7 +33,7 @@ class RunServerCommand extends Command
$this->setHelp("直接运行可以启动");
}
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
if (($opt = $input->getOption("env")) !== null) {
if (!in_array($opt, ["production", "staging", "development", ""])) {
$output->writeln("<error> \"--env\" option only accept production, development, staging and [empty] ! </error>");

View File

@ -13,7 +13,7 @@ class SystemdCommand extends Command
// the name of the command (the part after "bin/console")
protected static $defaultName = 'systemd:generate';
protected function execute(InputInterface $input, OutputInterface $output) {
protected function execute(InputInterface $input, OutputInterface $output): int {
//TODO: 写一个生成systemd配置的功能给2.0
return Command::SUCCESS;
}

View File

@ -18,8 +18,8 @@ use ZM\Utils\DataProvider;
class ConsoleApplication extends Application
{
const VERSION_ID = 387;
const VERSION = "2.3.0";
const VERSION_ID = 388;
const VERSION = "2.3.1";
public function __construct(string $name = 'UNKNOWN') {
define("ZM_VERSION_ID", self::VERSION_ID);
@ -27,7 +27,7 @@ class ConsoleApplication extends Application
parent::__construct($name, ZM_VERSION);
}
public function initEnv() {
public function initEnv(): ConsoleApplication {
$this->selfCheck();
if (!is_dir(__DIR__ . '/../../vendor')) {
@ -90,7 +90,7 @@ class ConsoleApplication extends Application
* @param OutputInterface|null $output
* @return int
*/
public function run(InputInterface $input = null, OutputInterface $output = null) {
public function run(InputInterface $input = null, OutputInterface $output = null): int {
try {
return parent::run($input, $output);
} catch (Exception $e) {
@ -98,7 +98,7 @@ class ConsoleApplication extends Application
}
}
private function selfCheck() {
private function selfCheck(): bool {
if (!extension_loaded("swoole")) die("Can not find swoole extension.\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/19\n");
if (version_compare(SWOOLE_VERSION, "4.4.13") == -1) die("You must install swoole version >= 4.4.13 !");
if (version_compare(PHP_VERSION, "7.2") == -1) die("PHP >= 7.2 required.");

View File

@ -8,11 +8,12 @@ use Co;
use Exception;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
use swoole_server;
use Swoole\WebSocket\Server;
use ZM\ConnectionManager\ConnectionObject;
use ZM\ConnectionManager\ManagerGM;
use ZM\Console\Console;
use ZM\Event\EventDispatcher;
use ZM\Exception\InterruptException;
use ZM\Exception\InvalidArgumentException;
use ZM\Exception\WaitTimeoutException;
use ZM\Http\Response;
@ -27,19 +28,19 @@ class Context implements ContextInterface
public function __construct($cid) { $this->cid = $cid; }
/**
* @return swoole_server|null
* @return Server
*/
public function getServer() { return self::$context[$this->cid]["server"] ?? server(); }
public function getServer(): ?Server { return self::$context[$this->cid]["server"] ?? server(); }
/**
* @return Frame|null
*/
public function getFrame() { return self::$context[$this->cid]["frame"] ?? null; }
public function getFrame(): ?Frame { return self::$context[$this->cid]["frame"] ?? null; }
public function getFd() { return self::$context[$this->cid]["fd"] ?? $this->getFrame()->fd ?? null; }
public function getFd(): ?int { return self::$context[$this->cid]["fd"] ?? $this->getFrame()->fd ?? null; }
/**
* @return array|null
* @return mixed
*/
public function getData() { return self::$context[$this->cid]["data"] ?? null; }
@ -48,25 +49,25 @@ class Context implements ContextInterface
/**
* @return Request|null
*/
public function getRequest() { return self::$context[$this->cid]["request"] ?? null; }
public function getRequest(): ?Request { return self::$context[$this->cid]["request"] ?? null; }
/**
* @return Response|null
*/
public function getResponse() { return self::$context[$this->cid]["response"] ?? null; }
public function getResponse(): ?Response { return self::$context[$this->cid]["response"] ?? null; }
/** @return ConnectionObject|null */
/** @return ConnectionObject|null|Response */
public function getConnection() { return ManagerGM::get($this->getFd()); }
/**
* @return int|null
*/
public function getCid() { return $this->cid; }
public function getCid(): ?int { return $this->cid; }
/**
* @return ZMRobot|null
*/
public function getRobot() {
public function getRobot(): ?ZMRobot {
$conn = ManagerGM::get($this->getFrame()->fd);
return $conn instanceof ConnectionObject ? new ZMRobot($conn) : null;
}
@ -87,7 +88,7 @@ class Context implements ContextInterface
public function setDiscussId($id) { self::$context[$this->cid]["data"]["discuss_id"] = $id; }
public function getMessageType() { return $this->getData()["message_type"] ?? null; }
public function getMessageType(): ?string { return $this->getData()["message_type"] ?? null; }
public function setMessageType($type) { self::$context[$this->cid]["data"]["message_type"] = $type; }
@ -104,6 +105,7 @@ class Context implements ContextInterface
* @param $msg
* @param bool $yield
* @return mixed
* @noinspection PhpMissingReturnTypeInspection
*/
public function reply($msg, $yield = false) {
$data = $this->getData();
@ -131,6 +133,12 @@ class Context implements ContextInterface
}
}
/**
* @param $msg
* @param false $yield
* @return mixed|void
* @throws InterruptException
*/
public function finalReply($msg, $yield = false) {
self::$context[$this->cid]["cache"]["block_continue"] = true;
if ($msg != "") $this->reply($msg, $yield);
@ -144,6 +152,7 @@ class Context implements ContextInterface
* @return string
* @throws InvalidArgumentException
* @throws WaitTimeoutException
* @noinspection PhpMissingReturnTypeInspection
*/
public function waitMessage($prompt = "", $timeout = 600, $timeout_prompt = "") {
if (!isset($this->getData()["user_id"], $this->getData()["message"], $this->getData()["self_id"]))
@ -258,6 +267,7 @@ class Context implements ContextInterface
*/
public function getNumArg($prompt_msg = "") { return $this->getArgs(ZM_MATCH_NUMBER, $prompt_msg); }
/** @noinspection PhpMissingReturnTypeInspection */
public function cloneFromParent() {
set_coroutine_params(self::$context[Co::getPcid()] ?? self::$context[$this->cid]);
return context();

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\Context;

View File

@ -1,4 +1,6 @@
<?php /** @noinspection PhpComposerExtensionStubsInspection */
<?php /** @noinspection PhpUnused */
/** @noinspection PhpComposerExtensionStubsInspection */
namespace ZM\DB;
@ -34,7 +36,7 @@ class DB
* @return Table
* @throws DbException
*/
public static function table($table_name) {
public static function table($table_name): Table {
if (Table::getTableInstance($table_name) === null) {
if (in_array($table_name, self::$table_list))
return new Table($table_name);
@ -60,7 +62,7 @@ class DB
* @return bool
* @throws DbException
*/
public static function unprepared($line) {
public static function unprepared($line): bool {
try {
$conn = SqlPoolStorage::$sql_pool->get();
if ($conn === false) {
@ -134,7 +136,7 @@ class DB
}
}
public static function isTableExists($table) {
public static function isTableExists($table): bool {
return in_array($table, self::$table_list);
}
}

View File

@ -32,7 +32,7 @@ class SelectBody
/**
* @throws DbException
*/
public function count() {
public function count(): int {
$this->select_thing = ["count(*)"];
$str = $this->queryPrepare();
$this->result = DB::rawQuery($str[0], $str[1]);
@ -81,7 +81,7 @@ class SelectBody
public function getResult() { return $this->result; }
public function equals(SelectBody $body) {
public function equals(SelectBody $body): bool {
if ($this->select_thing != $body->getSelectThing()) return false;
elseif ($this->where_thing == $body->getWhereThing()) return false;
else return true;
@ -95,9 +95,9 @@ class SelectBody
/**
* @return array
*/
public function getWhereThing() { return $this->where_thing; }
public function getWhereThing(): array { return $this->where_thing; }
private function queryPrepare() {
private function queryPrepare(): array {
$msg = "SELECT " . implode(", ", $this->select_thing) . " FROM " . $this->table->getTableName();
$sql = $this->table->paintWhereSQL($this->where_thing['='] ?? [], '=');
if ($sql[0] != '') {

View File

@ -1,4 +1,6 @@
<?php
<?php /** @noinspection PhpUnused */
/** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\DB;

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\DB;

View File

@ -20,7 +20,7 @@ class CQObject
}
}
public static function fromArray($arr) {
public static function fromArray($arr): CQObject {
return new CQObject($arr["type"], $arr["params"] ?? [], $arr["start"], $arr["end"]);
}
}

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Event;
@ -9,7 +9,6 @@ use Error;
use Exception;
use ZM\Console\Console;
use ZM\Exception\InterruptException;
use ZM\Exception\ZMException;
use ZM\Store\LightCacheInside;
use ZM\Store\Lock\SpinLock;
use ZM\Store\ZMAtomic;
@ -32,7 +31,7 @@ class EventDispatcher
/** @var bool */
private $log = false;
/** @var int */
private $eid = 0;
private $eid;
/** @var int */
public $status = self::STATUS_NORMAL;
/** @var mixed */
@ -64,22 +63,18 @@ class EventDispatcher
public function __construct(string $class = '') {
$this->class = $class;
try {
$this->eid = ZMAtomic::get("_event_id")->add(1);
$list = LightCacheInside::get("wait_api", "event_trace");
} catch (ZMException $e) {
$list = [];
}
$this->eid = ZMAtomic::get("_event_id")->add(1);
$list = LightCacheInside::get("wait_api", "event_trace");
if (isset($list[$class])) $this->log = true;
if ($this->log) Console::verbose("[事件分发{$this->eid}] 开始分发事件: " . $class);
}
public function setRuleFunction(callable $rule = null) {
public function setRuleFunction(callable $rule = null): EventDispatcher {
$this->rule = $rule;
return $this;
}
public function setReturnFunction(callable $return_func) {
public function setReturnFunction(callable $return_func): EventDispatcher {
$this->return_func = $return_func;
return $this;
}
@ -117,6 +112,7 @@ class EventDispatcher
* @return bool
* @throws InterruptException
* @throws AnnotationException
* @noinspection PhpMissingReturnTypeInspection
*/
public function dispatchEvent($v, $rule_func = null, ...$params) {
$q_c = $v->class;

View File

@ -9,7 +9,6 @@ use Exception;
use Swoole\Timer;
use ZM\Annotation\AnnotationBase;
use ZM\Annotation\AnnotationParser;
use ZM\Annotation\Swoole\OnSave;
use ZM\Annotation\Swoole\OnTick;
use ZM\Config\ZMConfig;
use ZM\Console\Console;
@ -37,6 +36,7 @@ class EventManager
/**
* 注册所有计时器给每个进程
* @throws Exception
*/
public static function registerTimerTick() {
$dispatcher = new EventDispatcher(OnTick::class);

View File

@ -127,6 +127,7 @@ class ServerEventHandler
* @SwooleHandler("WorkerStop")
* @param $server
* @param $worker_id
* @throws Exception
*/
public function onWorkerStop(Server $server, $worker_id) {
if ($worker_id == (ZMConfig::get("worker_cache")["worker"] ?? 0)) {
@ -598,7 +599,6 @@ class ServerEventHandler
* @param Server|null $server
* @param Server\Task $task
* @noinspection PhpUnusedParameterInspection
* @return null
*/
public function onTask(?Server $server, Server\Task $task) {
if (isset($task->data["task"])) {

View File

@ -340,7 +340,7 @@ class Framework
} else { // 输出很小,写到前面并分片
//Console::info("输出很小,写到前面并分片");
$space = intval($max_border / 2) - 2 - strlen($tmp_line);
$line_data[$current_line] .= str_pad("", $space, " ");
$line_data[$current_line] .= str_pad("", $space);
$line_data[$current_line] .= "| "; // 添加分片
$line_width[$current_line] -= (strlen($tmp_line) + 3 + $space);
}
@ -392,7 +392,7 @@ class Framework
echo str_pad("", $max_border, "=") . PHP_EOL;
}
public static function getTtyWidth() {
public static function getTtyWidth(): string {
return explode(" ", trim(exec("stty size")))[1];
}
}

View File

@ -1,4 +1,6 @@
<?php
<?php /** @noinspection PhpUnused */
/** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\Http;

View File

@ -55,7 +55,7 @@ class QQBot
* @return EventDispatcher
* @throws Exception
*/
public function dispatchBeforeEvents($data) {
public function dispatchBeforeEvents($data): EventDispatcher {
$before = new EventDispatcher(CQBefore::class);
$before->setRuleFunction(function ($v) use ($data) {
return $v->cq_event == $data["post_type"];
@ -70,6 +70,7 @@ class QQBot
/**
* @param $data
* @throws InterruptException
* @throws Exception
*/
private function dispatchEvents($data) {
//Console::warning("最xia数据包".json_encode($data));

View File

@ -27,6 +27,7 @@ class LightCache
* @param $config
* @return bool|mixed
* @throws Exception
* @noinspection PhpMissingReturnTypeInspection
*/
public static function init($config) {
self::$config = $config;
@ -87,6 +88,7 @@ class LightCache
* @param int $expire
* @return mixed
* @throws ZMException
* @noinspection PhpMissingReturnTypeInspection
*/
public static function set(string $key, $value, int $expire = -1) {
if (self::$kv_table === null) throw new ZMException("not initialized LightCache");
@ -120,6 +122,7 @@ class LightCache
* @param $value
* @return bool|mixed
* @throws ZMException
* @noinspection PhpMissingReturnTypeInspection
*/
public static function update(string $key, $value) {
if (self::$kv_table === null) throw new ZMException("not initialized LightCache.");
@ -154,7 +157,7 @@ class LightCache
* @return bool
* @throws Exception
*/
public static function isset(string $key) {
public static function isset(string $key): bool {
return self::get($key) !== null;
}
@ -162,7 +165,7 @@ class LightCache
return self::$kv_table->del($key);
}
public static function getAll() {
public static function getAll(): array {
$r = [];
$del = [];
foreach (self::$kv_table as $k => $v) {
@ -178,8 +181,11 @@ class LightCache
return $r;
}
/**
* @param false $only_worker
* @throws Exception
*/
public static function savePersistence($only_worker = false) {
// 下面将OnSave激活一下
if (server()->worker_id == (ZMConfig::get("global", "worker_cache")["worker"] ?? 0)) {
$dispatcher = new EventDispatcher(OnSave::class);

View File

@ -13,12 +13,14 @@ class LightCacheInside
/** @var Table[]|null */
private static $kv_table = [];
public static $last_error = '';
public static function init() {
self::createTable("wait_api", 3, 65536); //用于存协程等待的状态内容的
self::createTable("connect", 3, 64); //用于存单机器人模式下的机器人fd的
self::createTable("static_route", 64, 256);//用于存储
public static function init(): bool {
try {
self::createTable("wait_api", 3, 65536);
self::createTable("connect", 3, 64); //用于存单机器人模式下的机器人fd的
self::createTable("static_route", 64, 256);//用于存储
} catch (ZMException $e) {
return false;
} //用于存协程等待的状态内容的
//self::createTable("worker_start", 2, 1024);//用于存启动服务器时的状态的
return true;
}
@ -27,10 +29,8 @@ class LightCacheInside
* @param string $table
* @param string $key
* @return mixed|null
* @throws ZMException
*/
public static function get(string $table, string $key) {
if (!isset(self::$kv_table[$table])) throw new ZMException("not initialized LightCache");
$r = self::$kv_table[$table]->get($key);
return $r === false ? null : json_decode($r["value"], true);
}
@ -40,10 +40,8 @@ class LightCacheInside
* @param string $key
* @param string|array|int $value
* @return mixed
* @throws ZMException
*/
public static function set(string $table, string $key, $value) {
if (self::$kv_table === null) throw new ZMException("not initialized LightCache");
public static function set(string $table, string $key, $value): bool {
try {
return self::$kv_table[$table]->set($key, [
"value" => json_encode($value, 256)

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Store\Lock;
@ -29,7 +29,7 @@ class SpinLock
}
}
public static function tryLock(string $key) {
public static function tryLock(string $key): bool {
if (($r = self::$kv_lock->incr($key, 'lock_num')) > 1) {
return false;
}

View File

@ -1,4 +1,6 @@
<?php /** @noinspection PhpComposerExtensionStubsInspection */
<?php /** @noinspection PhpUnused */
/** @noinspection PhpComposerExtensionStubsInspection */
namespace ZM\Store\Redis;
@ -36,7 +38,7 @@ class ZMRedis
/**
* @return Redis
*/
public function get() {
public function get(): Redis {
return $this->conn;
}

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\Store;

View File

@ -16,7 +16,7 @@ class ZMAtomic
* @param $name
* @return Atomic|null
*/
public static function get($name) {
public static function get($name): ?Atomic {
return self::$atomics[$name] ?? null;
}

View File

@ -5,7 +5,6 @@ namespace ZM\Utils;
use Co;
use Exception;
use ZM\Store\LightCacheInside;
use ZM\Store\Lock\SpinLock;
use ZM\Store\ZMAtomic;
@ -17,7 +16,7 @@ class CoMessage
* @param array $compare
* @param int $timeout
* @return mixed
* @throws Exception
* @noinspection PhpMissingReturnTypeInspection
*/
public static function yieldByWS(array $hang, array $compare, $timeout = 600) {
$cid = Co::getuid();
@ -40,7 +39,7 @@ class CoMessage
Co::suspend();
SpinLock::lock("wait_api");
$sess = LightCacheInside::get("wait_api", "wait_api");
$result = $sess[$api_id]["result"];
$result = $sess[$api_id]["result"] ?? null;
unset($sess[$api_id]);
LightCacheInside::set("wait_api", "wait_api", $sess);
SpinLock::unlock("wait_api");
@ -49,7 +48,7 @@ class CoMessage
return $result;
}
public static function resumeByWS() {
public static function resumeByWS(): bool {
$dat = ctx()->getData();
$last = null;
SpinLock::lock("wait_api");

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Utils;
@ -11,7 +11,7 @@ class DataProvider
{
public static $buffer_list = [];
public static function getResourceFolder() {
public static function getResourceFolder(): string {
return self::getWorkingDir() . '/resources/';
}

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpMissingReturnTypeInspection */
namespace ZM\Utils;
@ -17,6 +17,7 @@ use ZM\Http\RouteManager;
class HttpUtil
{
/** @noinspection PhpMissingReturnTypeInspection */
public static function parseUri($request, $response, $uri, &$node, &$params) {
$context = new RequestContext();
$context->setMethod($request->server['request_method']);

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Utils;
@ -7,7 +7,6 @@ namespace ZM\Utils;
use ZM\API\CQ;
use ZM\Config\ZMConfig;
use ZM\Console\Console;
use ZM\Framework;
use ZM\Requests\ZMRequest;
class MessageUtil
@ -46,7 +45,7 @@ class MessageUtil
* @param $msg
* @return bool
*/
public static function containsImage($msg) {
public static function containsImage($msg): bool {
$cq = CQ::getAllCQ($msg, true);
foreach ($cq as $v) {
if ($v->type == "image") {
@ -65,7 +64,7 @@ class MessageUtil
* @param int $type
* @return string
*/
public static function getImageCQFromLocal($file, $type = 0) {
public static function getImageCQFromLocal($file, $type = 0): string {
switch ($type) {
case 0:
return CQ::image("base64://" . base64_encode(file_get_contents($file)));

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Utils;

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Utils;
@ -15,6 +15,7 @@ trait SingletonTrait
/**
* @return self
* @noinspection PhpMissingReturnTypeInspection
*/
public static function getInstance() {
if (null === self::$instance) {

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Utils;
@ -8,6 +8,13 @@ use ZM\Console\Console;
class TaskManager
{
/**
* @noinspection PhpMissingReturnTypeInspection
* @param $task_name
* @param int $timeout
* @param mixed ...$params
* @return false|mixed
*/
public static function runTask($task_name, $timeout = -1, ...$params) {
if (!isset(server()->setting["task_worker_num"])) {
Console::warning("未开启 TaskWorker 进程,请先修改 global 配置文件启用!");

View File

@ -1,4 +1,4 @@
<?php
<?php /** @noinspection PhpUnused */
namespace ZM\Utils;
@ -16,6 +16,8 @@ class Terminal
* @param string $cmd
* @param $resource
* @return bool
* @noinspection PhpMissingReturnTypeInspection
* @noinspection PhpUnused
*/
public static function executeCommand(string $cmd, $resource) {
$it = explodeMsg($cmd);

View File

@ -17,6 +17,9 @@ use ZM\Store\ZMBuf;
class ZMUtil
{
/**
* @throws Exception
*/
public static function stop() {
if (SpinLock::tryLock("_stop_signal") === false) return;
Console::warning(Console::setColor("Stopping server...", "red"));
@ -33,6 +36,10 @@ class ZMUtil
server()->stop();
}
/**
* @param int $delay
* @throws Exception
*/
public static function reload($delay = 800) {
if (server()->worker_id !== -1) {
Console::info(server()->worker_id);

View File

@ -1,6 +1,8 @@
<?php #plain
<?php /** @noinspection PhpUnused */ #plain
use Swoole\Atomic;
use Swoole\Coroutine;
use Swoole\WebSocket\Server;
use ZM\API\ZMRobot;
use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM;
@ -11,6 +13,7 @@ use ZM\Exception\RobotNotFoundException;
use ZM\Exception\ZMException;
use ZM\Framework;
use ZM\Store\LightCacheInside;
use ZM\Store\ZMAtomic;
use ZM\Store\ZMBuf;
use ZM\Utils\DataProvider;
use Swoole\Coroutine\System;
@ -52,7 +55,7 @@ function getClassPath($class_name) {
* @param bool $ban_comma
* @return array
*/
function explodeMsg($msg, $ban_comma = false) {
function explodeMsg($msg, $ban_comma = false): array {
$msg = str_replace(" ", "\n", trim($msg));
if (!$ban_comma) {
//$msg = str_replace("", "\n", $msg);
@ -79,7 +82,7 @@ function unicode_decode($str) {
* @param $indoor_name
* @return array
*/
function getAllClasses($dir, $indoor_name) {
function getAllClasses($dir, $indoor_name): array {
if (!is_dir($dir)) return [];
$list = scandir($dir);
$classes = [];
@ -104,7 +107,7 @@ function getAllClasses($dir, $indoor_name) {
return $classes;
}
function matchPattern($pattern, $context) {
function matchPattern($pattern, $context): bool {
if (mb_substr($pattern, 0, 1) == "" && mb_substr($context, 0, 1) == "")
return true;
if ('*' == mb_substr($pattern, 0, 1) && "" != mb_substr($pattern, 1, 1) && "" == mb_substr($context, 0, 1))
@ -116,7 +119,7 @@ function matchPattern($pattern, $context) {
return false;
}
function split_explode($del, $str, $divide_en = false) {
function split_explode($del, $str, $divide_en = false): array {
$str = explode($del, $str);
for ($i = 0; $i < mb_strlen($str[0]); $i++) {
if (
@ -178,19 +181,19 @@ function matchArgs($pattern, $context) {
} else return false;
}
function connectIsQQ() {
function connectIsQQ(): bool {
return ctx()->getConnection()->getName() == 'qq';
}
function connectIsDefault() {
function connectIsDefault(): bool {
return ctx()->getConnection()->getName() == 'default';
}
function connectIs($type) {
function connectIs($type): bool {
return ctx()->getConnection()->getName() == $type;
}
function getAnnotations() {
function getAnnotations(): array {
$s = debug_backtrace()[1];
//echo json_encode($s, 128|256);
$list = [];
@ -218,14 +221,14 @@ function set_coroutine_params($array) {
/**
* @return ContextInterface|null
*/
function context() {
function context(): ?ContextInterface {
return ctx();
}
/**
* @return ContextInterface|null
*/
function ctx() {
function ctx(): ?ContextInterface {
$cid = Co::getCid();
$c_class = ZMConfig::get("global", "context_class");
if (isset(Context::$context[$cid])) {
@ -242,11 +245,11 @@ function ctx() {
function zm_debug($msg) { Console::debug($msg); }
function onebot_target_id_name($message_type) {
function onebot_target_id_name($message_type): string {
return ($message_type == "group" ? "group_id" : "user_id");
}
function zm_sleep($s = 1) {
function zm_sleep($s = 1): bool {
if (Coroutine::getCid() != -1) System::sleep($s);
else usleep($s * 1000 * 1000);
return true;
@ -291,11 +294,11 @@ function zm_timer_tick($ms, callable $callable) {
}
}
function zm_data_hash($v) {
function zm_data_hash($v): string {
return md5($v["user_id"] . "^" . $v["self_id"] . "^" . $v["message_type"] . "^" . ($v[$v["message_type"] . "_id"] ?? $v["user_id"]));
}
function server() {
function server(): ?Server {
return Framework::$server;
}
@ -304,7 +307,7 @@ function server() {
* @throws RobotNotFoundException
* @throws ZMException
*/
function bot() {
function bot(): ZMRobot {
if (($conn = LightCacheInside::get("connect", "conn_fd")) == -2) {
return ZMRobot::getRandom();
} elseif ($conn != -1) {
@ -329,11 +332,11 @@ function getAllFdByConnectType(string $type = 'default'): array {
return $fds;
}
function zm_atomic($name) {
return \ZM\Store\ZMAtomic::get($name);
function zm_atomic($name): ?Atomic {
return ZMAtomic::get($name);
}
function uuidgen($uppercase = false) {
function uuidgen($uppercase = false): string {
try {
$data = random_bytes(16);
} catch (Exception $e) {

View File

@ -1,256 +0,0 @@
<?php
namespace ZMTest\Mock;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
use ZM\API\ZMRobot;
use ZM\ConnectionManager\ConnectionObject;
use ZM\Context\ContextInterface;
use ZM\Http\Response;
class Context implements ContextInterface
{
/**
* Context constructor.
* @param $cid
*/
public function __construct($cid) { }
/**
* @return Server
*/
public function getServer() {
// TODO: Implement getServer() method.
}
/**
* @return Frame
*/
public function getFrame() {
// TODO: Implement getFrame() method.
}
/**
* @return mixed
*/
public function getData() {
// TODO: Implement getData() method.
}
/**
* @param $data
* @return mixed
*/
public function setData($data) {
// TODO: Implement setData() method.
}
/**
* @return ConnectionObject
*/
public function getConnection() {
// TODO: Implement getConnection() method.
}
/**
* @return int|null
*/
public function getFd() {
// TODO: Implement getFd() method.
}
/**
* @return int
*/
public function getCid() {
// TODO: Implement getCid() method.
}
/**
* @return Response
*/
public function getResponse() {
// TODO: Implement getResponse() method.
}
/**
* @return Request
*/
public function getRequest() {
// TODO: Implement getRequest() method.
}
/**
* @return ZMRobot
*/
public function getRobot() {
// TODO: Implement getRobot() method.
}
/**
* @return mixed
*/
public function getUserId() {
// TODO: Implement getUserId() method.
}
/**
* @return mixed
*/
public function getGroupId() {
// TODO: Implement getGroupId() method.
}
/**
* @return mixed
*/
public function getDiscussId() {
// TODO: Implement getDiscussId() method.
}
/**
* @return string
*/
public function getMessageType() {
// TODO: Implement getMessageType() method.
}
/**
* @return mixed
*/
public function getRobotId() {
// TODO: Implement getRobotId() method.
}
/**
* @return mixed
*/
public function getMessage() {
// TODO: Implement getMessage() method.
}
/**
* @param $msg
* @return mixed
*/
public function setMessage($msg) {
// TODO: Implement setMessage() method.
}
/**
* @param $id
* @return mixed
*/
public function setUserId($id) {
// TODO: Implement setUserId() method.
}
/**
* @param $id
* @return mixed
*/
public function setGroupId($id) {
// TODO: Implement setGroupId() method.
}
/**
* @param $id
* @return mixed
*/
public function setDiscussId($id) {
// TODO: Implement setDiscussId() method.
}
/**
* @param $type
* @return mixed
*/
public function setMessageType($type) {
// TODO: Implement setMessageType() method.
}
/**
* @return mixed
*/
public function getCQResponse() {
// TODO: Implement getCQResponse() method.
}
/**
* @param $msg
* @param bool $yield
* @return mixed
*/
public function reply($msg, $yield = false) {
echo $msg.PHP_EOL;
// TODO: Implement reply() method.
}
/**
* @param $msg
* @param bool $yield
* @return mixed
*/
public function finalReply($msg, $yield = false) {
// TODO: Implement finalReply() method.
}
/**
* @param string $prompt
* @param int $timeout
* @param string $timeout_prompt
* @return mixed
*/
public function waitMessage($prompt = "", $timeout = 600, $timeout_prompt = "") {
// TODO: Implement waitMessage() method.
}
/**
* @param $arg
* @param $mode
* @param $prompt_msg
* @return mixed
*/
public function getArgs(&$arg, $mode, $prompt_msg) {
$r = $arg;
array_shift($r);
return array_shift($r);
// TODO: Implement getArgs() method.
}
/**
* @param $key
* @param $value
* @return mixed
*/
public function setCache($key, $value) {
// TODO: Implement setCache() method.
}
/**
* @param $key
* @return mixed
*/
public function getCache($key) {
// TODO: Implement getCache() method.
}
/**
* @return mixed
*/
public function cloneFromParent() {
// TODO: Implement cloneFromParent() method.
}
/**
* @return mixed
*/
public function copy() {
// TODO: Implement copy() method.
}
}

View File

@ -1,111 +0,0 @@
<?php
/** @noinspection PhpFullyQualifiedNameUsageInspection */
/** @noinspection PhpComposerExtensionStubsInspection */
global $config;
/** bind host */
$config['host'] = '0.0.0.0';
/** bind port */
$config['port'] = 20001;
/** 框架开到公网或外部的HTTP访问链接通过 DataProvider::getFrameworkLink() 获取 */
$config['http_reverse_link'] = "http://127.0.0.1:" . $config['port'];
/** 框架是否启动debug模式 */
$config['debug_mode'] = false;
/** 存放框架内文件数据的目录 */
$config['zm_data'] = realpath(__DIR__ . "/../") . '/zm_data/';
/** 存放崩溃和运行日志的目录 */
$config['crash_dir'] = $config['zm_data'] . 'crash/';
/** 对应swoole的server->set参数 */
$config['swoole'] = [
'log_file' => $config['crash_dir'] . 'swoole_error.log',
'worker_num' => 8,
'dispatch_mode' => 2,
'max_coroutine' => 30000,
//'task_worker_num' => 4,
//'task_enable_coroutine' => true
];
/** 轻量字符串缓存,默认开启 */
$config['light_cache'] = [
"status" => true,
"size" => 2048, //最多允许储存的条数需要2的倍数
"max_strlen" => 4096, //单行字符串最大长度需要2的倍数
"hash_conflict_proportion" => 0.6 //Hash冲突率越大越好但是需要的内存更多
];
/** MySQL数据库连接信息host留空则启动时不创建sql连接池 */
$config['sql_config'] = [
'sql_host' => '',
'sql_port' => 3306,
'sql_username' => 'name',
'sql_database' => 'db_name',
'sql_password' => '',
'sql_enable_cache' => true,
'sql_reset_cache' => '0300',
'sql_options' => [
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_EMULATE_PREPARES => false
],
'sql_no_exception' => false,
'sql_default_fetch_mode' => PDO::FETCH_ASSOC // added in 1.5.6
];
/** CQHTTP连接约定的token */
$config["access_token"] = "";
/** HTTP服务器固定请求头的返回 */
$config['http_header'] = [
'X-Powered-By' => 'zhamao-framework',
'Content-Type' => 'text/html; charset=utf-8'
];
/** HTTP服务器在指定状态码下回复的页面默认 */
$config['http_default_code_page'] = [
'404' => '404.html'
];
/** zhamao-framework在框架启动时初始化的atomic们 */
$config['init_atomics'] = [
//'custom_atomic_name' => 0, //自定义添加的Atomic
];
/** 终端日志显示等级0-4 */
$config["info_level"] = 2;
/** 自动保存计时器的缓存保存时间(秒) */
$config['auto_save_interval'] = 900;
/** 上下文接口类 implemented from ContextInterface */
$config['context_class'] = \ZMTest\Mock\Context::class;
/** 静态文件访问 */
$config['static_file_server'] = [
'status' => false,
'document_root' => realpath(__DIR__ . "/../") . '/resources/html',
'document_index' => [
'index.html'
]
];
/** 注册 Swoole Server 事件注解的类列表 */
$config['server_event_handler_class'] = [
\ZM\Event\ServerEventHandler::class,
];
/** 注册自定义指令的类 */
$config['command_register_class'] = [
//\Custom\Command\CustomCommand::class
];
/** 服务器启用的外部第三方和内部插件 */
$config['modules'] = [
'onebot' => true, // QQ机器人事件解析器如果取消此项则默认为 true 开启状态,否则你手动填写 false 才会关闭
];
return $config;

View File

@ -40,10 +40,7 @@ class EventDispatcherTest extends TestCase
$dispatcher->setRuleFunction(function ($v) { return $v->match == "你好"; });
//$dispatcher->setRuleFunction(fn ($v) => $v->match == "qwe");
ob_start();
try {
$dispatcher->dispatchEvents();
} catch (AnnotationException $e) {
}
$dispatcher->dispatchEvents();
$r = ob_get_clean();
echo $r;
$this->assertStringContainsString("你好啊", $r);