mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-22 08:05:34 +08:00
initial commit
This commit is contained in:
94
src/ZM/Event/Swoole/MessageEvent.php
Normal file
94
src/ZM/Event/Swoole/MessageEvent.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Event\Swoole;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Framework\Console;
|
||||
use Framework\ZMBuf;
|
||||
use Swoole\WebSocket\Frame;
|
||||
use Swoole\WebSocket\Server;
|
||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
||||
use ZM\Annotation\Swoole\SwooleEventAt;
|
||||
use ZM\Connection\ConnectionManager;
|
||||
use Exception;
|
||||
use ZM\Event\EventHandler;
|
||||
use ZM\ModBase;
|
||||
use ZM\ModHandleType;
|
||||
use ZM\Utils\ZMUtil;
|
||||
|
||||
class MessageEvent implements SwooleEvent
|
||||
{
|
||||
/**
|
||||
* @var Server
|
||||
*/
|
||||
public $server;
|
||||
/**
|
||||
* @var Frame
|
||||
*/
|
||||
public $frame;
|
||||
|
||||
public function __construct(Server $server, Frame $frame) {
|
||||
$this->server = $server;
|
||||
$this->frame = $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onActivate() {
|
||||
ZMUtil::checkWait();
|
||||
try {
|
||||
if (ConnectionManager::get($this->frame->fd)->getType() == "qq") {
|
||||
$data = json_decode($this->frame->data, true);
|
||||
if (isset($data["post_type"]))
|
||||
EventHandler::callCQEvent($data, $this, 0);
|
||||
else
|
||||
EventHandler::callCQResponse($data);
|
||||
}
|
||||
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "message" && $this->parseSwooleRule($v)) {
|
||||
$conn = ConnectionManager::get($this->frame->fd);
|
||||
$c = $v->class;
|
||||
/** @var ModBase $class */
|
||||
$class = new $c(["server" => $this->server, "frame" => $this->frame, "connection" => $conn], ModHandleType::SWOOLE_MESSAGE);
|
||||
call_user_func_array([$class, $v->method], [$conn]);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Console::error("出现错误: " . $e->getMessage());
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onAfter() {
|
||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "message" && $this->parseSwooleRule($v) === true) {
|
||||
$conn = ConnectionManager::get($this->frame->fd);
|
||||
$c = $v->class;
|
||||
/** @var ModBase $class */
|
||||
$class = new $c(["server" => $this->server, "frame" => $this->frame, "connection" => $conn], ModHandleType::SWOOLE_MESSAGE);
|
||||
call_user_func_array([$class, $v->method], []);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function parseSwooleRule($v) {
|
||||
switch (explode(":", $v->rule)[0]) {
|
||||
case "connectType": //websocket连接类型
|
||||
if ($v->callback instanceof Closure) return call_user_func($v->callback, ConnectionManager::get($this->frame->fd));
|
||||
break;
|
||||
case "dataEqual": //handle websocket message事件时才能用
|
||||
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->frame->data);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
132
src/ZM/Event/Swoole/RequestEvent.php
Normal file
132
src/ZM/Event/Swoole/RequestEvent.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Event\Swoole;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Framework\ZMBuf;
|
||||
use Swoole\Http\Request;
|
||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
||||
use ZM\Annotation\Swoole\SwooleEventAt;
|
||||
use ZM\Http\Response;
|
||||
use ZM\ModBase;
|
||||
use ZM\ModHandleType;
|
||||
use ZM\Utils\ZMUtil;
|
||||
|
||||
class RequestEvent implements SwooleEvent
|
||||
{
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
private $request;
|
||||
/**
|
||||
* @var Response
|
||||
*/
|
||||
private $response;
|
||||
|
||||
public function __construct(Request $request, Response $response) {
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onActivate() {
|
||||
ZMUtil::checkWait();
|
||||
foreach (ZMBuf::globals("http_header") as $k => $v) {
|
||||
$this->response->setHeader($k, $v);
|
||||
}
|
||||
$uri = $this->request->server["request_uri"];
|
||||
if ($uri != "/") {
|
||||
$uri = explode("/", $uri);
|
||||
$uri = array_diff($uri, ["..", "", "."]);
|
||||
$node = ZMBuf::$req_mapping_node;
|
||||
$params = [];
|
||||
while (true) {
|
||||
$r = array_shift($uri);
|
||||
if ($r === null) break;
|
||||
if (($node2 = $node->getRealRoute($r, $params)) !== null) {
|
||||
$node = $node2;
|
||||
continue;
|
||||
} else {
|
||||
$this->responseStatus(404);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
if ($node->getRule() === null || call_user_func($node->getRule(), $this->request) === true) { //判断规则是否存在,如果有规则则走一遍规则
|
||||
if (in_array(strtoupper($this->request->server["request_method"]), $node->getRequestMethod())) { //判断目标方法在不在里面
|
||||
$c_name = $node->getClass();
|
||||
/** @var ModBase $class */
|
||||
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
|
||||
$r = call_user_func_array([$class, $node->getMethod()], [$params]);
|
||||
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
|
||||
if ($class->block_continue) return $this;
|
||||
if ($this->response->isEnd()) return $this;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (($node = ZMBuf::$req_mapping_node)->getMethod() !== null) {
|
||||
if (in_array(strtoupper($this->request->server["request_method"]), $node->getRequestMethod())) { //判断目标方法在不在里面
|
||||
$c_name = $node->getClass();
|
||||
/** @var ModBase $class */
|
||||
$class = new $c_name(["request" => $this->request, "response" => $this->response], ModHandleType::SWOOLE_REQUEST);
|
||||
$r = call_user_func_array([$class, $node->getMethod()], []);
|
||||
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
|
||||
if ($class->block_continue) return $this;
|
||||
if ($this->response->isEnd()) return $this;
|
||||
}
|
||||
}
|
||||
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
|
||||
$c = $v->class;
|
||||
$class = new $c(["request" => $this->request, "response" => $this->response]);
|
||||
$r = call_user_func_array([$class, $v->method], []);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->response->isEnd()) {
|
||||
$this->response->status(404);
|
||||
$this->response->end(ZMUtil::getHttpCodePage(404));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onAfter() {
|
||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
|
||||
$c = $v->class;
|
||||
$class = new $c(["request" => $this->request, "response" => $this->response]);
|
||||
call_user_func_array([$class, $v->method], []);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function responseStatus(int $int) {
|
||||
$this->response->status($int);
|
||||
$this->response->end();
|
||||
}
|
||||
|
||||
private function parseSwooleRule($v) {
|
||||
switch ($v->rule) {
|
||||
case "containsGet":
|
||||
case "containsPost":
|
||||
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->request);
|
||||
break;
|
||||
case "containsJson":
|
||||
$content = $this->request->rawContent();
|
||||
$content = json_decode($content, true);
|
||||
if ($content === null) return false;
|
||||
if ($v->callback instanceof Closure) return call_user_func($v->callback, $content);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
20
src/ZM/Event/Swoole/SwooleEvent.php
Normal file
20
src/ZM/Event/Swoole/SwooleEvent.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Event\Swoole;
|
||||
|
||||
|
||||
use ZM\Event\Event;
|
||||
|
||||
interface SwooleEvent extends Event
|
||||
{
|
||||
/**
|
||||
* @return SwooleEvent
|
||||
*/
|
||||
public function onActivate();
|
||||
|
||||
/**
|
||||
* @return SwooleEvent
|
||||
*/
|
||||
public function onAfter();
|
||||
}
|
||||
61
src/ZM/Event/Swoole/WSCloseEvent.php
Normal file
61
src/ZM/Event/Swoole/WSCloseEvent.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Event\Swoole;
|
||||
|
||||
|
||||
use Framework\ZMBuf;
|
||||
use Swoole\Server;
|
||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
||||
use ZM\Annotation\Swoole\SwooleEventAt;
|
||||
use ZM\ModBase;
|
||||
use ZM\ModHandleType;
|
||||
use ZM\Utils\ZMUtil;
|
||||
|
||||
class WSCloseEvent implements SwooleEvent
|
||||
{
|
||||
public $server;
|
||||
|
||||
public $fd;
|
||||
|
||||
public function __construct(Server $server, int $fd) {
|
||||
$this->server = $server;
|
||||
$this->fd = $fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onActivate() {
|
||||
ZMUtil::checkWait();
|
||||
foreach(ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||
if(strtolower($v->type) == "close" && $this->parseSwooleRule($v)) {
|
||||
$c = $v->class;
|
||||
$class = new $c(["server" => $this->server, "fd" => $this->fd], ModHandleType::SWOOLE_CLOSE);
|
||||
call_user_func_array([$class, $v->method], []);
|
||||
if($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onAfter() {
|
||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "close" && $this->parseSwooleRule($v) === true) {
|
||||
$c = $v->class;
|
||||
/** @var ModBase $class */
|
||||
$class = new $c(["server" => $this->server, "fd" => $this->fd], ModHandleType::SWOOLE_CLOSE);
|
||||
call_user_func_array([$class, $v->method], []);
|
||||
if($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function parseSwooleRule($v) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
93
src/ZM/Event/Swoole/WSOpenEvent.php
Normal file
93
src/ZM/Event/Swoole/WSOpenEvent.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Event\Swoole;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Framework\ZMBuf;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\WebSocket\Server;
|
||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
||||
use ZM\Annotation\Swoole\SwooleEventAt;
|
||||
use ZM\Connection\ConnectionManager;
|
||||
use ZM\Connection\CQConnection;
|
||||
use ZM\Connection\UnknownConnection;
|
||||
use ZM\Connection\WSConnection;
|
||||
use ZM\ModBase;
|
||||
use ZM\ModHandleType;
|
||||
use ZM\Utils\ZMUtil;
|
||||
|
||||
class WSOpenEvent implements SwooleEvent
|
||||
{
|
||||
/**
|
||||
* @var Server
|
||||
*/
|
||||
private $server;
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
private $request;
|
||||
/**
|
||||
* @var WSConnection
|
||||
*/
|
||||
private $conn;
|
||||
|
||||
public function __construct(Server $server, Request $request) {
|
||||
$this->server = $server;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onActivate() {
|
||||
ZMUtil::checkWait();
|
||||
$type = strtolower($this->request->get["type"] ?? $this->request->header["x-client-role"] ?? "");
|
||||
$type_conn = ConnectionManager::getTypeClassName($type);
|
||||
if ($type_conn == CQConnection::class) {
|
||||
$qq = $this->request->get["qq"] ?? $this->request->header["x-self-id"] ?? "";
|
||||
$self_token = ZMBuf::globals("access_token") ?? "";
|
||||
$remote_token = $this->request->get["token"] ?? (isset($header["authorization"]) ? explode(" ", $this->request->header["authorization"])[1] : "");
|
||||
if ($qq != "" && ($self_token == $remote_token)) $this->conn = new CQConnection($this->server, $this->request->fd, $qq);
|
||||
else $this->conn = new UnknownConnection($this->server, $this->request->fd);
|
||||
} else {
|
||||
$this->conn = new $type_conn($this->server, $this->request->fd);
|
||||
}
|
||||
ZMBuf::$connect[$this->request->fd] = $this->conn;
|
||||
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "open" && $this->parseSwooleRule($v) === true) {
|
||||
$c = $v->class;
|
||||
$class = new $c(["server" => $this->server, "request" => $this->request, "connection" => $this->conn], ModHandleType::SWOOLE_OPEN);
|
||||
call_user_func_array([$class, $v->method], [$this->conn]);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function onAfter() {
|
||||
if (!$this->conn->exists()) return $this;
|
||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||
if (strtolower($v->type) == "open" && $this->parseSwooleRule($v) === true) {
|
||||
/** @var ModBase $class */
|
||||
$class = new $v["class"](["server" => $this->server, "request" => $this->request, "connection" => $this->conn], ModHandleType::SWOOLE_OPEN);
|
||||
call_user_func_array([$class, $v["method"]], [$this->conn]);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function parseSwooleRule($v) {
|
||||
switch (explode(":", $v->rule)[0]) {
|
||||
case "connectType": //websocket连接类型
|
||||
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->conn);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
137
src/ZM/Event/Swoole/WorkerStartEvent.php
Normal file
137
src/ZM/Event/Swoole/WorkerStartEvent.php
Normal file
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace ZM\Event\Swoole;
|
||||
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationException;
|
||||
use ReflectionException;
|
||||
use Swoole\Coroutine;
|
||||
use Swoole\Timer;
|
||||
use ZM\Annotation\AnnotationBase;
|
||||
use ZM\Annotation\AnnotationParser;
|
||||
use ZM\Annotation\MappingNode;
|
||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
||||
use ZM\Connection\ConnectionManager;
|
||||
use ZM\DB\DB;
|
||||
use ZM\DBCache\DBCacheManager;
|
||||
use Framework\Console;
|
||||
use Framework\GlobalConfig;
|
||||
use Framework\ZMBuf;
|
||||
use Swoole\Server;
|
||||
use ZM\ModBase;
|
||||
use ZM\ModHandleType;
|
||||
use ZM\Utils\DataProvider;
|
||||
use ZM\Utils\SQLPool;
|
||||
|
||||
class WorkerStartEvent implements SwooleEvent
|
||||
{
|
||||
private $worker_id;
|
||||
/**
|
||||
* @var Server
|
||||
*/
|
||||
private $server;
|
||||
|
||||
public function __construct(Server $server, $worker_id) {
|
||||
$this->server = $server;
|
||||
$this->worker_id = $worker_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WorkerStartEvent
|
||||
* @throws AnnotationException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function onActivate(): WorkerStartEvent {
|
||||
Console::info("Worker启动中");
|
||||
ZMBuf::resetCache(); //清空变量缓存
|
||||
ZMBuf::set("wait_start", []); //添加队列,在workerStart运行完成前先让其他协程等待执行
|
||||
DBCacheManager::freeAllCache(); // 清空数据库缓存
|
||||
$this->resetConnections();//释放所有与framework的连接
|
||||
|
||||
//设置炸毛buf中储存的对象
|
||||
ZMBuf::$globals = new GlobalConfig();
|
||||
if (ZMBuf::globals("sql_config")["sql_host"] != "") {
|
||||
Console::info("新建SQL连接池中");
|
||||
ZMBuf::$sql_pool = new SQLPool();
|
||||
DB::initTableList();
|
||||
}
|
||||
ZMBuf::$server = $this->server;
|
||||
ZMBuf::$atomics['reload_time']->add(1);
|
||||
ZMBuf::$req_mapping_node = new MappingNode("/");
|
||||
|
||||
Console::info("监听console输入");
|
||||
Console::listenConsole(); //这个方法只能在这里调用,且如果worker_num不为1的话,此功能不可用
|
||||
|
||||
$this->loadAllClass(); //加载composer资源、phar外置包、注解解析注册等
|
||||
|
||||
$this->setAutosaveTimer(ZMBuf::globals("auto_save_interval"));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onAfter(): WorkerStartEvent {
|
||||
foreach (ZMBuf::get("wait_start") as $v) {
|
||||
Coroutine::resume($v);
|
||||
}
|
||||
ZMBuf::unsetCache("wait_start");
|
||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||
/** @var AnnotationBase $v */
|
||||
if (strtolower($v->type) == "workerstart") {
|
||||
$class_name = $v->class;
|
||||
/** @var ModBase $class */
|
||||
$class = new $class_name(["server" => $this->server, "worker_id" => $this->worker_id], ModHandleType::SWOOLE_WORKER_START);
|
||||
call_user_func_array([$class, $v->method], []);
|
||||
if ($class->block_continue) break;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function resetConnections() {
|
||||
foreach ($this->server->connections as $v) {
|
||||
$this->server->close($v);
|
||||
}
|
||||
if (ZMBuf::$sql_pool instanceof SqlPool) {
|
||||
ZMBuf::$sql_pool->destruct();
|
||||
ZMBuf::$sql_pool = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AnnotationException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function loadAllClass() {
|
||||
//加载phar包
|
||||
Console::info("加载外部phar包中");
|
||||
$dir = WORKING_DIR . "/resources/package/";
|
||||
if (is_dir($dir)) {
|
||||
$list = scandir($dir);
|
||||
unset($list[0], $list[1]);
|
||||
foreach ($list as $v) {
|
||||
if (is_dir($dir . $v)) continue;
|
||||
if (pathinfo($dir . $v, 4) == "phar") require_once($dir . $v);
|
||||
}
|
||||
}
|
||||
|
||||
//加载composer类
|
||||
Console::info("加载composer资源中");
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
require_once WORKING_DIR . "/vendor/autoload.php";
|
||||
|
||||
//加载各个模块的注解类,以及反射
|
||||
Console::info("检索Module中");
|
||||
AnnotationParser::registerMods();
|
||||
|
||||
//加载Custom目录下的自定义的内部类
|
||||
ConnectionManager::registerCustomClass();
|
||||
}
|
||||
|
||||
private function setAutosaveTimer($globals) {
|
||||
DataProvider::$buffer_list = [];
|
||||
Timer::tick($globals * 1000, function() {
|
||||
DataProvider::saveBuffer();
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user