fix:修复BUG/升级1.1.6版本
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
"homepage": "http://www.workerman.net",
|
||||
"license" : "MIT",
|
||||
"require": {
|
||||
"php": ">=7.0",
|
||||
"workerman/workerman" : "^4.0.30"
|
||||
},
|
||||
"autoload": {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of workerman.
|
||||
*
|
||||
@@ -51,20 +52,6 @@ class BusinessWorker extends Worker
|
||||
*/
|
||||
public $eventHandler = 'Events';
|
||||
|
||||
/**
|
||||
* 业务超时时间,可用来定位程序卡在哪里
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $processTimeout = 30;
|
||||
|
||||
/**
|
||||
* 业务超时时间,可用来定位程序卡在哪里
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
public $processTimeoutHandler = '\\Workerman\\Worker::log';
|
||||
|
||||
/**
|
||||
* 秘钥
|
||||
*
|
||||
@@ -82,21 +69,21 @@ class BusinessWorker extends Worker
|
||||
/**
|
||||
* 保存用户设置的 worker 启动回调
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onWorkerStart = null;
|
||||
|
||||
/**
|
||||
* 保存用户设置的 workerReload 回调
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onWorkerReload = null;
|
||||
|
||||
/**
|
||||
* 保存用户设置的 workerStop 回调
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onWorkerStop= null;
|
||||
|
||||
@@ -131,21 +118,21 @@ class BusinessWorker extends Worker
|
||||
/**
|
||||
* Event::onConnect 回调
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_eventOnConnect = null;
|
||||
|
||||
/**
|
||||
* Event::onMessage 回调
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_eventOnMessage = null;
|
||||
|
||||
/**
|
||||
* Event::onClose 回调
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_eventOnClose = null;
|
||||
|
||||
@@ -227,13 +214,6 @@ class BusinessWorker extends Worker
|
||||
call_user_func($this->eventHandler . '::onWorkerStart', $this);
|
||||
}
|
||||
|
||||
if (function_exists('pcntl_signal')) {
|
||||
// 业务超时信号处理
|
||||
pcntl_signal(SIGALRM, array($this, 'timeoutHandler'), false);
|
||||
} else {
|
||||
$this->processTimeout = 0;
|
||||
}
|
||||
|
||||
// 设置回调
|
||||
if (is_callable($this->eventHandler . '::onConnect')) {
|
||||
$this->_eventOnConnect = $this->eventHandler . '::onConnect';
|
||||
@@ -393,9 +373,6 @@ class BusinessWorker extends Worker
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->processTimeout) {
|
||||
pcntl_alarm($this->processTimeout);
|
||||
}
|
||||
// 尝试执行 Event::onConnection、Event::onMessage、Event::onClose
|
||||
switch ($cmd) {
|
||||
case GatewayProtocol::CMD_ON_CONNECT:
|
||||
@@ -420,9 +397,6 @@ class BusinessWorker extends Worker
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ($this->processTimeout) {
|
||||
pcntl_alarm(0);
|
||||
}
|
||||
|
||||
// session 必须是数组
|
||||
if ($_SESSION !== null && !is_array($_SESSION)) {
|
||||
@@ -447,7 +421,7 @@ class BusinessWorker extends Worker
|
||||
*/
|
||||
public function onGatewayClose($connection)
|
||||
{
|
||||
$addr = $connection->remoteAddress;
|
||||
$addr = $connection->remoteAddr;
|
||||
unset($this->gatewayConnections[$addr], $this->_connectingGatewayAddresses[$addr]);
|
||||
if (isset($this->_gatewayAddresses[$addr]) && !isset($this->_waitingConnectGatewayAddresses[$addr])) {
|
||||
Timer::add(1, array($this, 'tryToConnectGateway'), array($addr), false);
|
||||
@@ -464,7 +438,7 @@ class BusinessWorker extends Worker
|
||||
{
|
||||
if (!isset($this->gatewayConnections[$addr]) && !isset($this->_connectingGatewayAddresses[$addr]) && isset($this->_gatewayAddresses[$addr])) {
|
||||
$gateway_connection = new AsyncTcpConnection("GatewayProtocol://$addr");
|
||||
$gateway_connection->remoteAddress = $addr;
|
||||
$gateway_connection->remoteAddr = $addr;
|
||||
$gateway_connection->onConnect = array($this, 'onConnectGateway');
|
||||
$gateway_connection->onMessage = array($this, 'onGatewayMessage');
|
||||
$gateway_connection->onClose = array($this, 'onGatewayClose');
|
||||
@@ -513,8 +487,8 @@ class BusinessWorker extends Worker
|
||||
*/
|
||||
public function onConnectGateway($connection)
|
||||
{
|
||||
$this->gatewayConnections[$connection->remoteAddress] = $connection;
|
||||
unset($this->_connectingGatewayAddresses[$connection->remoteAddress], $this->_waitingConnectGatewayAddresses[$connection->remoteAddress]);
|
||||
$this->gatewayConnections[$connection->remoteAddr] = $connection;
|
||||
unset($this->_connectingGatewayAddresses[$connection->remoteAddr], $this->_waitingConnectGatewayAddresses[$connection->remoteAddr]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,28 +512,4 @@ class BusinessWorker extends Worker
|
||||
{
|
||||
return $this->_gatewayAddresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务超时回调
|
||||
*
|
||||
* @param int $signal
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function timeoutHandler($signal)
|
||||
{
|
||||
switch ($signal) {
|
||||
// 超时时钟
|
||||
case SIGALRM:
|
||||
// 超时异常
|
||||
$e = new \Exception("process_timeout", 506);
|
||||
$trace_str = $e->getTraceAsString();
|
||||
// 去掉第一行timeoutHandler的调用栈
|
||||
$trace_str = $e->getMessage() . ":\n" . substr($trace_str, strpos($trace_str, "\n") + 1) . "\n";
|
||||
// 开发者没有设置超时处理函数,或者超时处理函数返回空则执行退出
|
||||
if (!$this->processTimeoutHandler || !call_user_func($this->processTimeoutHandler, $trace_str, $e)) {
|
||||
Worker::stopAll();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
70
vendor/workerman/gateway-worker/src/Gateway.php
vendored
70
vendor/workerman/gateway-worker/src/Gateway.php
vendored
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of workerman.
|
||||
*
|
||||
@@ -38,7 +39,7 @@ class Gateway extends Worker
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '3.0.22';
|
||||
const VERSION = '3.0.28';
|
||||
|
||||
/**
|
||||
* 本机 IP
|
||||
@@ -48,6 +49,21 @@ class Gateway extends Worker
|
||||
*/
|
||||
public $lanIp = '127.0.0.1';
|
||||
|
||||
/**
|
||||
* 如果宿主机为192.168.1.2 , gatewayworker in docker container (172.25.0.2)
|
||||
* 此时 lanIp=192.68.1.2 GatewayClientSDK 能连上,但是$this->_innerTcpWorker stream_socket_server(): Unable to connect to tcp://192.168.1.2:2901 (Address not available) in
|
||||
* 此时 lanIp=172.25.0.2 GatewayClientSDK stream_socket_server(): Unable to connect to tcp://172.25.0.2:2901 (Address not available) , $this->_innerTcpWorker 正常监听
|
||||
*
|
||||
* solution:
|
||||
* $gateway->lanIp=192.168.1.2 ;
|
||||
* $gateway->innerTcpWorkerListen=172.25.0.2; // || 0.0.0.0
|
||||
*
|
||||
* GatewayClientSDK connect 192.168.1.2:lanPort
|
||||
* $this->_innerTcpWorker listen $gateway->innerTcpWorkerListen:lanPort
|
||||
*
|
||||
*/
|
||||
public $innerTcpWorkerListen='';
|
||||
|
||||
/**
|
||||
* 本机端口
|
||||
*
|
||||
@@ -107,7 +123,7 @@ class Gateway extends Worker
|
||||
/**
|
||||
* 路由函数
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
public $router = null;
|
||||
|
||||
@@ -136,14 +152,14 @@ class Gateway extends Worker
|
||||
/**
|
||||
* BusinessWorker 连接成功之后触发
|
||||
*
|
||||
* @var callback|null
|
||||
* @var callable|null
|
||||
*/
|
||||
public $onBusinessWorkerConnected = null;
|
||||
|
||||
/**
|
||||
* BusinessWorker 关闭时触发
|
||||
*
|
||||
* @var callback|null
|
||||
* @var callable|null
|
||||
*/
|
||||
public $onBusinessWorkerClose = null;
|
||||
|
||||
@@ -183,35 +199,35 @@ class Gateway extends Worker
|
||||
/**
|
||||
* 当 worker 启动时
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onWorkerStart = null;
|
||||
|
||||
/**
|
||||
* 当有客户端连接时
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onConnect = null;
|
||||
|
||||
/**
|
||||
* 当客户端发来消息时
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onMessage = null;
|
||||
|
||||
/**
|
||||
* 当客户端连接关闭时
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onClose = null;
|
||||
|
||||
/**
|
||||
* 当 worker 停止时
|
||||
*
|
||||
* @var callback
|
||||
* @var callable|null
|
||||
*/
|
||||
protected $_onWorkerStop = null;
|
||||
|
||||
@@ -348,15 +364,35 @@ class Gateway extends Worker
|
||||
* websocket握手时触发
|
||||
*
|
||||
* @param $connection
|
||||
* @param $http_buffer
|
||||
* @param $request
|
||||
*/
|
||||
public function onWebsocketConnect($connection, $http_buffer)
|
||||
public function onWebsocketConnect($connection, $request)
|
||||
{
|
||||
if (isset($connection->_onWebSocketConnect)) {
|
||||
call_user_func($connection->_onWebSocketConnect, $connection, $http_buffer);
|
||||
call_user_func($connection->_onWebSocketConnect, $connection, $request);
|
||||
unset($connection->_onWebSocketConnect);
|
||||
}
|
||||
$this->sendToWorker(GatewayProtocol::CMD_ON_WEBSOCKET_CONNECT, $connection, array('get' => $_GET, 'server' => $_SERVER, 'cookie' => $_COOKIE));
|
||||
if (is_object($request)) {
|
||||
$server = [
|
||||
'QUERY_STRING' => $request->queryString(),
|
||||
'REQUEST_METHOD' => $request->method(),
|
||||
'REQUEST_URI' => $request->uri(),
|
||||
'SERVER_PROTOCOL' => "HTTP/" . $request->protocolVersion(),
|
||||
'SERVER_NAME' => $request->host(false),
|
||||
'CONTENT_TYPE' => $request->header('content-type'),
|
||||
'REMOTE_ADDR' => $connection->getRemoteIp(),
|
||||
'REMOTE_PORT' => $connection->getRemotePort(),
|
||||
'SERVER_PORT' => $connection->getLocalPort(),
|
||||
];
|
||||
foreach ($request->header() as $key => $header) {
|
||||
$key = str_replace('-', '_', strtoupper($key));
|
||||
$server["HTTP_$key"] = $header;
|
||||
}
|
||||
$data = array('get' => $request->get(), 'server' => $server, 'cookie' => $request->cookie());
|
||||
} else {
|
||||
$data = array('get' => $_GET, 'server' => $_SERVER, 'cookie' => $_COOKIE);
|
||||
}
|
||||
$this->sendToWorker(GatewayProtocol::CMD_ON_WEBSOCKET_CONNECT, $connection, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -506,13 +542,19 @@ class Gateway extends Worker
|
||||
|
||||
//如为公网IP监听,直接换成0.0.0.0 ,否则用内网IP
|
||||
$listen_ip=filter_var($this->lanIp,FILTER_VALIDATE_IP,FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)?'0.0.0.0':$this->lanIp;
|
||||
|
||||
//Use scenario to see line 64
|
||||
if($this->innerTcpWorkerListen != '') {
|
||||
$listen_ip = $this->innerTcpWorkerListen;
|
||||
}
|
||||
|
||||
// 初始化 gateway 内部的监听,用于监听 worker 的连接已经连接上发来的数据
|
||||
$this->_innerTcpWorker = new Worker("GatewayProtocol://{$listen_ip}:{$this->lanPort}");
|
||||
$this->_innerTcpWorker->reusePort = false;
|
||||
$this->_innerTcpWorker->listen();
|
||||
$this->_innerTcpWorker->name = 'GatewayInnerWorker';
|
||||
|
||||
if ($this->_autoloadRootPath) {
|
||||
if ($this->_autoloadRootPath && class_exists(Autoloader::class)) {
|
||||
Autoloader::setRootPath($this->_autoloadRootPath);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,14 +52,20 @@ class Gateway
|
||||
* 与Gateway是否是长链接
|
||||
* @var bool
|
||||
*/
|
||||
public static $persistentConnection = false;
|
||||
public static $persistentConnection = true;
|
||||
|
||||
/**
|
||||
* 是否清除注册地址缓存
|
||||
* @var bool
|
||||
*/
|
||||
public static $addressesCacheDisable = false;
|
||||
|
||||
|
||||
/**
|
||||
* 与gateway建立的连接
|
||||
* @var array
|
||||
*/
|
||||
protected static $gatewayConnections = [];
|
||||
|
||||
/**
|
||||
* 向所有客户端连接(或者 client_id_array 指定的客户端连接)广播消息
|
||||
*
|
||||
@@ -758,8 +764,8 @@ class Gateway
|
||||
$client_array = $status_data = $client_address_map = $receive_buffer_array = $recv_length_array = array();
|
||||
// 批量向所有gateway进程发送请求数据
|
||||
foreach ($gateway_buffer_array as $address => $gateway_buffer) {
|
||||
$client = stream_socket_client("tcp://$address", $errno, $errmsg, static::$connectTimeout);
|
||||
if ($client && strlen($gateway_buffer) === stream_socket_sendto($client, $gateway_buffer)) {
|
||||
$client = static::getGatewayConnection("tcp://$address");
|
||||
if (strlen($gateway_buffer) === stream_socket_sendto($client, $gateway_buffer)) {
|
||||
$socket_id = (int)$client;
|
||||
$client_array[$socket_id] = $client;
|
||||
$client_address_map[$socket_id] = explode(':', $address);
|
||||
@@ -792,6 +798,7 @@ class Gateway
|
||||
}
|
||||
}
|
||||
if (microtime(true) - $time_start > $timeout) {
|
||||
static::$gatewayConnections = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1154,10 +1161,8 @@ class Gateway
|
||||
{
|
||||
$buffer = GatewayProtocol::encode($data);
|
||||
$buffer = static::$secretKey ? static::generateAuthBuffer() . $buffer : $buffer;
|
||||
$client = stream_socket_client("tcp://$address", $errno, $errmsg, static::$connectTimeout);
|
||||
if (!$client) {
|
||||
throw new Exception("can not connect to tcp://$address $errmsg");
|
||||
}
|
||||
$address = "tcp://$address";
|
||||
$client = static::getGatewayConnection($address);
|
||||
if (strlen($buffer) === stream_socket_sendto($client, $buffer)) {
|
||||
$timeout = 5;
|
||||
// 阻塞读
|
||||
@@ -1173,8 +1178,10 @@ class Gateway
|
||||
$all_buffer .= $buf;
|
||||
} else {
|
||||
if (feof($client)) {
|
||||
throw new Exception("connection close tcp://$address");
|
||||
unset(static::$gatewayConnections[$address]);
|
||||
throw new Exception("connection close $address");
|
||||
} elseif (microtime(true) - $time_start > $timeout) {
|
||||
unset(static::$gatewayConnections[$address]);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -1183,8 +1190,12 @@ class Gateway
|
||||
if (!$pack_len && $recv_len >= 4) {
|
||||
$pack_len= current(unpack('N', $all_buffer));
|
||||
}
|
||||
if (microtime(true) - $time_start > $timeout) {
|
||||
unset(static::$gatewayConnections[$address]);
|
||||
break;
|
||||
}
|
||||
// 回复的数据都是以\n结尾
|
||||
if (($pack_len && $recv_len >= $pack_len + 4) || microtime(true) - $time_start > $timeout) {
|
||||
if (($pack_len && $recv_len >= $pack_len + 4)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1224,8 +1235,7 @@ class Gateway
|
||||
}
|
||||
// 非workerman环境
|
||||
$gateway_buffer = static::$secretKey ? static::generateAuthBuffer() . $gateway_buffer : $gateway_buffer;
|
||||
$flag = static::$persistentConnection ? STREAM_CLIENT_PERSISTENT | STREAM_CLIENT_CONNECT : STREAM_CLIENT_CONNECT;
|
||||
$client = stream_socket_client("tcp://$address", $errno, $errmsg, static::$connectTimeout, $flag);
|
||||
$client = static::getGatewayConnection("tcp://$address");
|
||||
return strlen($gateway_buffer) == stream_socket_sendto($client, $gateway_buffer);
|
||||
}
|
||||
|
||||
@@ -1373,6 +1383,44 @@ class Gateway
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取与gateway的连接,用于数据返回
|
||||
*
|
||||
* @param $address
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
protected static function getGatewayConnection($address)
|
||||
{
|
||||
$ttl = 50;
|
||||
$time = time();
|
||||
if (isset(static::$gatewayConnections[$address])) {
|
||||
$created_time = static::$gatewayConnections[$address]['created_time'];
|
||||
$connection = static::$gatewayConnections[$address]['connection'];
|
||||
if ($time - $created_time > $ttl || !is_resource($connection) || feof($connection)) {
|
||||
\set_error_handler(function () {});
|
||||
fclose($connection);
|
||||
\restore_error_handler();
|
||||
unset(static::$gatewayConnections[$address]);
|
||||
}
|
||||
}
|
||||
if (!isset(static::$gatewayConnections[$address])) {
|
||||
$client = stream_socket_client($address, $errno, $errmsg, static::$connectTimeout);
|
||||
if (!$client) {
|
||||
throw new Exception("can not connect to $address $errmsg");
|
||||
}
|
||||
static::$gatewayConnections[$address] = [
|
||||
'created_time' => $time,
|
||||
'connection' => $client
|
||||
];
|
||||
}
|
||||
$client = static::$gatewayConnections[$address]['connection'];
|
||||
if (!static::$persistentConnection) {
|
||||
static::$gatewayConnections = [];
|
||||
}
|
||||
return $client;
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('\Protocols\GatewayProtocol')) {
|
||||
|
||||
@@ -176,7 +176,7 @@ class GatewayProtocol
|
||||
$data['body'] = serialize($data['body']);
|
||||
}
|
||||
$data['flag'] |= $flag;
|
||||
$ext_len = strlen($data['ext_data']);
|
||||
$ext_len = strlen($data['ext_data']??'');
|
||||
$package_len = self::HEAD_LEN + $ext_len + strlen($data['body']);
|
||||
return pack("NCNnNnNCnN", $package_len,
|
||||
$data['cmd'], $data['local_ip'],
|
||||
|
||||
@@ -161,6 +161,7 @@ class Register extends Worker
|
||||
*/
|
||||
public function onClose($connection)
|
||||
{
|
||||
Timer::del($connection->timeout_timerid);
|
||||
if (isset($this->_gatewayConnections[$connection->id])) {
|
||||
unset($this->_gatewayConnections[$connection->id]);
|
||||
$this->broadcastAddresses();
|
||||
|
||||
4
vendor/workerman/redis-queue/composer.json
vendored
4
vendor/workerman/redis-queue/composer.json
vendored
@@ -6,8 +6,8 @@
|
||||
"description": "Message queue system written in PHP based on workerman and backed by Redis.",
|
||||
"require": {
|
||||
"php": ">=5.4",
|
||||
"workerman/redis" : "^1.0",
|
||||
"workerman/workerman" : "^4.0.20"
|
||||
"workerman/redis" : "^1.0||^2.0",
|
||||
"workerman/workerman" : ">=4.0.20"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"Workerman\\RedisQueue\\": "./src"}
|
||||
|
||||
1
vendor/workerman/redis-queue/src/Client.php
vendored
1
vendor/workerman/redis-queue/src/Client.php
vendored
@@ -22,6 +22,7 @@ use Workerman\Redis\Client as Redis;
|
||||
* Class Client
|
||||
* @package Workerman\RedisQueue
|
||||
*/
|
||||
#[\AllowDynamicProperties]
|
||||
class Client
|
||||
{
|
||||
/**
|
||||
|
||||
4
vendor/workerman/redis/composer.json
vendored
4
vendor/workerman/redis/composer.json
vendored
@@ -4,8 +4,8 @@
|
||||
"homepage": "http://www.workerman.net",
|
||||
"license" : "MIT",
|
||||
"require": {
|
||||
"php": ">=5.4",
|
||||
"workerman/workerman": ">=4.0.5"
|
||||
"php": ">=7",
|
||||
"workerman/workerman": "^4.1.0||^5.0.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"Workerman\\Redis\\": "./src"}
|
||||
|
||||
167
vendor/workerman/redis/src/Client.php
vendored
167
vendor/workerman/redis/src/Client.php
vendored
@@ -13,7 +13,9 @@
|
||||
*/
|
||||
namespace Workerman\Redis;
|
||||
|
||||
use Revolt\EventLoop;
|
||||
use Workerman\Connection\AsyncTcpConnection;
|
||||
use Workerman\Redis\Protocols\Redis;
|
||||
use Workerman\Timer;
|
||||
|
||||
/**
|
||||
@@ -48,12 +50,11 @@ use Workerman\Timer;
|
||||
* @method static bool expireAt($key, $timestamp, $cb = null)
|
||||
* @method static bool pexpireAt($key, $timestamp, $cb = null)
|
||||
* @method static array keys($pattern, $cb = null)
|
||||
* @method static bool|array scan($it, $cb = null)
|
||||
* @method static void migrate($host, $port, $keys, $dbIndex, $timeout, $copy = false, $replace = false, $cb = null)
|
||||
* @method static bool move($key, $dbIndex, $cb = null)
|
||||
* @method static string|int|bool object($information, $key, $cb = null)
|
||||
* @method static bool persist($key, $cb = null)
|
||||
* @method static string randomKey(, $cb = null)
|
||||
* @method static string randomKey($cb = null)
|
||||
* @method static bool rename($srcKey, $dstKey, $cb = null)
|
||||
* @method static bool renameNx($srcKey, $dstKey, $cb = null)
|
||||
* @method static string type($key, $cb = null)
|
||||
@@ -71,7 +72,6 @@ use Workerman\Timer;
|
||||
* @method static bool hExists($key, $hashKey, $cb = null)
|
||||
* @method static int hIncrBy($key, $hashKey, $value, $cb = null)
|
||||
* @method static float hIncrByFloat($key, $hashKey, $value, $cb = null)
|
||||
* @method static array hScan($key, $iterator, $pattern = '', $count = 0, $cb = null)
|
||||
* @method static int hStrLen($key, $hashKey, $cb = null)
|
||||
* Lists methods
|
||||
* @method static array blPop($keys, $timeout, $cb = null)
|
||||
@@ -106,7 +106,6 @@ use Workerman\Timer;
|
||||
* @method static int sRem($key, ...$members, $cb = null)
|
||||
* @method static array sUnion(...$keys, $cb = null)
|
||||
* @method static false|int sUnionStore($dst, ...$keys, $cb = null)
|
||||
* @method static false|array sScan($key, $iterator, $pattern = '', $count = 0, $cb = null)
|
||||
* Sorted sets methods
|
||||
* @method static array bzPopMin($keys, $timeout, $cb = null)
|
||||
* @method static array bzPopMax($keys, $timeout, $cb = null)
|
||||
@@ -129,7 +128,6 @@ use Workerman\Timer;
|
||||
* @method static array zRevRange($key, $start, $end, $withScores = false, $cb = null)
|
||||
* @method static double zScore($key, $member, $cb = null)
|
||||
* @method static int zunionstore($keyOutput, $arrayZSetKeys, $arrayWeights = [], $aggregateFunction = '', $cb = null)
|
||||
* @method static false|array zScan($key, $iterator, $pattern = '', $count = 0, $cb = null)
|
||||
* HyperLogLogs methods
|
||||
* @method static int pfAdd($key, $values, $cb = null)
|
||||
* @method static int pfCount($keys, $cb = null)
|
||||
@@ -161,7 +159,7 @@ use Workerman\Timer;
|
||||
* Generic methods
|
||||
* @method static mixed rawCommand(...$commandAndArgs, $cb = null)
|
||||
* Transactions methods
|
||||
* @method static \Redis multi($cb = null)
|
||||
* @method static multi($cb = null)
|
||||
* @method static mixed exec($cb = null)
|
||||
* @method static mixed discard($cb = null)
|
||||
* @method static mixed watch($keys, $cb = null)
|
||||
@@ -186,6 +184,7 @@ use Workerman\Timer;
|
||||
* @method static mixed getPersistentID($cb = null)
|
||||
* @method static mixed getAuth($cb = null)
|
||||
*/
|
||||
#[\AllowDynamicProperties]
|
||||
class Client
|
||||
{
|
||||
/**
|
||||
@@ -325,6 +324,10 @@ class Client
|
||||
$timeout = isset($this->_options['connect_timeout']) ? $this->_options['connect_timeout'] : 5;
|
||||
$context = isset($this->_options['context']) ? $this->_options['context'] : [];
|
||||
$this->_connection = new AsyncTcpConnection($this->_address, $context);
|
||||
$this->_connection->protocol = Redis::class;
|
||||
if(!empty($this->_options['ssl'])){
|
||||
$this->_connection->transport = 'ssl';
|
||||
}
|
||||
|
||||
$this->_connection->onConnect = function () {
|
||||
$this->_waiting = false;
|
||||
@@ -394,12 +397,8 @@ class Client
|
||||
}
|
||||
if (empty($this->_queue)) {
|
||||
$this->_queue = [];
|
||||
gc_collect_cycles();
|
||||
if (function_exists('gc_mem_caches')) {
|
||||
gc_mem_caches();
|
||||
}
|
||||
}
|
||||
$success = $type === '-' || $type === '!' ? false : true;
|
||||
$success = !($type === '-' || $type === '!');
|
||||
$exception = false;
|
||||
$result = false;
|
||||
if ($success) {
|
||||
@@ -530,6 +529,7 @@ class Client
|
||||
*
|
||||
* @param $db
|
||||
* @param null $cb
|
||||
* @return mixed
|
||||
*/
|
||||
public function select($db, $cb = null)
|
||||
{
|
||||
@@ -537,9 +537,16 @@ class Client
|
||||
$this->_db = $db;
|
||||
return $result;
|
||||
};
|
||||
$cb = $cb ? $cb : function(){};
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['SELECT', $db], time(), $cb, $format];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -547,6 +554,7 @@ class Client
|
||||
*
|
||||
* @param string|array $auth
|
||||
* @param null $cb
|
||||
* @return mixed
|
||||
*/
|
||||
public function auth($auth, $cb = null)
|
||||
{
|
||||
@@ -554,9 +562,16 @@ class Client
|
||||
$this->_auth = $auth;
|
||||
return $result;
|
||||
};
|
||||
$cb = $cb ? $cb : function(){};
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['AUTH', $auth], time(), $cb, $format];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -565,7 +580,7 @@ class Client
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @param null $cb
|
||||
* @return null
|
||||
* @return mixed
|
||||
*/
|
||||
public function set($key, $value, $cb = null)
|
||||
{
|
||||
@@ -576,12 +591,27 @@ class Client
|
||||
if (\count($args) > 3) {
|
||||
$cb = $args[3];
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['SETEX', $key, $timeout, $value], time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['SET', $key, $value], time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,7 +619,7 @@ class Client
|
||||
*
|
||||
* @param $key
|
||||
* @param null $cb
|
||||
* @return null
|
||||
* @return mixed
|
||||
*/
|
||||
public function incr($key, $cb = null)
|
||||
{
|
||||
@@ -600,12 +630,27 @@ class Client
|
||||
if (\count($args) > 2) {
|
||||
$cb = $args[2];
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['INCRBY', $key, $num], time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['INCR', $key], time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -614,7 +659,7 @@ class Client
|
||||
*
|
||||
* @param $key
|
||||
* @param null $cb
|
||||
* @return null
|
||||
* @return mixed
|
||||
*/
|
||||
public function decr($key, $cb = null)
|
||||
{
|
||||
@@ -625,12 +670,27 @@ class Client
|
||||
if (\count($args) > 2) {
|
||||
$cb = $args[2];
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['DECRBY', $key, $num], time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['DECR', $key], time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -639,6 +699,7 @@ class Client
|
||||
* @param $key
|
||||
* @param $options
|
||||
* @param null $cb
|
||||
* @return mixed
|
||||
*/
|
||||
function sort($key, $options, $cb = null)
|
||||
{
|
||||
@@ -659,8 +720,16 @@ class Client
|
||||
}
|
||||
}
|
||||
\array_unshift($args, 'SORT', $key);
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [$args, time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,7 +740,7 @@ class Client
|
||||
*/
|
||||
public function mSet(array $array, $cb = null)
|
||||
{
|
||||
$this->mapCb('MSET', $array, $cb);
|
||||
return $this->mapCb('MSET', $array, $cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -682,7 +751,7 @@ class Client
|
||||
*/
|
||||
public function mSetNx(array $array, $cb = null)
|
||||
{
|
||||
$this->mapCb('MSETNX', $array, $cb);
|
||||
return $this->mapCb('MSETNX', $array, $cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,6 +760,7 @@ class Client
|
||||
* @param $command
|
||||
* @param array $array
|
||||
* @param $cb
|
||||
* @return mixed
|
||||
*/
|
||||
protected function mapCb($command, array $array, $cb)
|
||||
{
|
||||
@@ -699,8 +769,16 @@ class Client
|
||||
$args[] = $key;
|
||||
$args[] = $value;
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [$args, time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -709,10 +787,11 @@ class Client
|
||||
* @param $key
|
||||
* @param array $array
|
||||
* @param null $cb
|
||||
* @return mixed
|
||||
*/
|
||||
public function hMSet($key, array $array, $cb = null)
|
||||
{
|
||||
$this->keyMapCb('HMSET', $key, $array, $cb);
|
||||
return $this->keyMapCb('HMSET', $key, $array, $cb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -721,6 +800,7 @@ class Client
|
||||
* @param $key
|
||||
* @param array $array
|
||||
* @param null $cb
|
||||
* @return mixed
|
||||
*/
|
||||
public function hMGet($key, array $array, $cb = null)
|
||||
{
|
||||
@@ -730,8 +810,16 @@ class Client
|
||||
}
|
||||
return \array_combine($array, $result);
|
||||
};
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['HMGET', $key, $array], time(), $cb, $format];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,6 +827,7 @@ class Client
|
||||
*
|
||||
* @param $key
|
||||
* @param null $cb
|
||||
* @return mixed
|
||||
*/
|
||||
public function hGetAll($key, $cb = null)
|
||||
{
|
||||
@@ -757,8 +846,16 @@ class Client
|
||||
}
|
||||
return $return;
|
||||
};
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [['HGETALL', $key], time(), $cb, $format];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -768,6 +865,7 @@ class Client
|
||||
* @param $key
|
||||
* @param array $array
|
||||
* @param $cb
|
||||
* @return mixed
|
||||
*/
|
||||
protected function keyMapCb($command, $key, array $array, $cb)
|
||||
{
|
||||
@@ -776,8 +874,16 @@ class Client
|
||||
$args[] = $key;
|
||||
$args[] = $value;
|
||||
}
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [$args, time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -785,6 +891,7 @@ class Client
|
||||
*
|
||||
* @param $method
|
||||
* @param $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
@@ -794,8 +901,28 @@ class Client
|
||||
}
|
||||
|
||||
\array_unshift($args, \strtoupper($method));
|
||||
$need_suspend = !$cb && class_exists(EventLoop::class, false);
|
||||
if ($need_suspend) {
|
||||
[$suspension, $cb] = $this->suspenstion();
|
||||
}
|
||||
$this->_queue[] = [$args, time(), $cb];
|
||||
$this->process();
|
||||
if ($need_suspend) {
|
||||
return $suspension->suspend();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function suspenstion()
|
||||
{
|
||||
$suspension = EventLoop::getSuspension();
|
||||
$cb = function ($result) use ($suspension) {
|
||||
$suspension->resume($result);
|
||||
};
|
||||
return [$suspension, $cb];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -808,7 +935,7 @@ class Client
|
||||
}
|
||||
$this->_subscribe = false;
|
||||
$this->_connection->onConnect = $this->_connection->onError = $this->_connection->onClose =
|
||||
$this->_connection->onMessge = null;
|
||||
$this->_connection->onMessage = null;
|
||||
$this->_connection->close();
|
||||
$this->_connection = null;
|
||||
if ($this->_connectTimeoutTimer) {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
open_collective: walkor
|
||||
patreon: walkor
|
||||
@@ -25,7 +25,8 @@
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/workerman": "^4.0.4",
|
||||
"ext-json": "*",
|
||||
"workerman/workerman": "^4.0.4 || ^5.0.0",
|
||||
"nikic/fast-route": "^1.3",
|
||||
"psr/container": ">=1.0"
|
||||
},
|
||||
|
||||
644
vendor/workerman/webman-framework/src/App.php
vendored
644
vendor/workerman/webman-framework/src/App.php
vendored
File diff suppressed because it is too large
Load Diff
@@ -21,8 +21,8 @@ interface Bootstrap
|
||||
/**
|
||||
* onWorkerStart
|
||||
*
|
||||
* @param Worker $worker
|
||||
* @param Worker|null $worker
|
||||
* @return mixed
|
||||
*/
|
||||
public static function start($worker);
|
||||
public static function start(?Worker $worker);
|
||||
}
|
||||
|
||||
144
vendor/workerman/webman-framework/src/Config.php
vendored
144
vendor/workerman/webman-framework/src/Config.php
vendored
@@ -14,79 +14,95 @@
|
||||
|
||||
namespace Webman;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use function array_replace_recursive;
|
||||
use function array_reverse;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function is_file;
|
||||
use function key;
|
||||
use function str_replace;
|
||||
|
||||
class Config
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_config = [];
|
||||
protected static $config = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $_configPath = '';
|
||||
protected static $configPath = '';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected static $_loaded = false;
|
||||
protected static $loaded = false;
|
||||
|
||||
/**
|
||||
* @param string $config_path
|
||||
* @param array $exclude_file
|
||||
* Load.
|
||||
* @param string $configPath
|
||||
* @param array $excludeFile
|
||||
* @param string|null $key
|
||||
* @return void
|
||||
*/
|
||||
public static function load(string $config_path, array $exclude_file = [], string $key = null)
|
||||
public static function load(string $configPath, array $excludeFile = [], string $key = null)
|
||||
{
|
||||
static::$_configPath = $config_path;
|
||||
if (!$config_path) {
|
||||
static::$configPath = $configPath;
|
||||
if (!$configPath) {
|
||||
return;
|
||||
}
|
||||
static::$_loaded = false;
|
||||
$config = static::loadFromDir($config_path, $exclude_file);
|
||||
static::$loaded = false;
|
||||
$config = static::loadFromDir($configPath, $excludeFile);
|
||||
if (!$config) {
|
||||
static::$_loaded = true;
|
||||
static::$loaded = true;
|
||||
return;
|
||||
}
|
||||
if ($key !== null) {
|
||||
foreach (\array_reverse(\explode('.', $key)) as $k) {
|
||||
foreach (array_reverse(explode('.', $key)) as $k) {
|
||||
$config = [$k => $config];
|
||||
}
|
||||
}
|
||||
static::$_config = \array_replace_recursive(static::$_config, $config);
|
||||
static::$config = array_replace_recursive(static::$config, $config);
|
||||
static::formatConfig();
|
||||
static::$_loaded = true;
|
||||
static::$loaded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This deprecated method will certainly be removed in the future
|
||||
*
|
||||
* @deprecated
|
||||
* @param string $config_path
|
||||
* @param array $exclude_file
|
||||
* This deprecated method will certainly be removed in the future.
|
||||
* @param string $configPath
|
||||
* @param array $excludeFile
|
||||
* @return void
|
||||
* @deprecated
|
||||
*/
|
||||
public static function reload(string $config_path, array $exclude_file = [])
|
||||
public static function reload(string $configPath, array $excludeFile = [])
|
||||
{
|
||||
static::load($config_path, $exclude_file);
|
||||
static::load($configPath, $excludeFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear.
|
||||
* @return void
|
||||
*/
|
||||
public static function clear()
|
||||
{
|
||||
static::$_config = [];
|
||||
static::$config = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* FormatConfig.
|
||||
* @return void
|
||||
*/
|
||||
protected static function formatConfig()
|
||||
{
|
||||
$config = static::$_config;
|
||||
$config = static::$config;
|
||||
// Merge log config
|
||||
foreach ($config['plugin'] ?? [] as $firm => $projects) {
|
||||
if (isset($projects['app'])) {
|
||||
@@ -95,7 +111,7 @@ class Config
|
||||
}
|
||||
}
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!\is_array($project)) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['log'] ?? [] as $key => $item) {
|
||||
@@ -111,7 +127,7 @@ class Config
|
||||
}
|
||||
}
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!\is_array($project)) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['database']['connections'] ?? [] as $key => $connection) {
|
||||
@@ -130,7 +146,7 @@ class Config
|
||||
}
|
||||
}
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!\is_array($project)) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['thinkorm']['connections'] ?? [] as $key => $connection) {
|
||||
@@ -139,7 +155,7 @@ class Config
|
||||
}
|
||||
}
|
||||
if (!empty($config['thinkorm']['connections'])) {
|
||||
$config['thinkorm']['default'] = $config['thinkorm']['default'] ?? \key($config['thinkorm']['connections']);
|
||||
$config['thinkorm']['default'] = $config['thinkorm']['default'] ?? key($config['thinkorm']['connections']);
|
||||
}
|
||||
// Merge redis config
|
||||
foreach ($config['plugin'] ?? [] as $firm => $projects) {
|
||||
@@ -149,7 +165,7 @@ class Config
|
||||
}
|
||||
}
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!\is_array($project)) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['redis'] ?? [] as $key => $connection) {
|
||||
@@ -157,33 +173,34 @@ class Config
|
||||
}
|
||||
}
|
||||
}
|
||||
static::$_config = $config;
|
||||
static::$config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $config_path
|
||||
* @param array $exclude_file
|
||||
* LoadFromDir.
|
||||
* @param string $configPath
|
||||
* @param array $excludeFile
|
||||
* @return array
|
||||
*/
|
||||
public static function loadFromDir(string $config_path, array $exclude_file = [])
|
||||
public static function loadFromDir(string $configPath, array $excludeFile = []): array
|
||||
{
|
||||
$all_config = [];
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($config_path, \FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
$allConfig = [];
|
||||
$dirIterator = new RecursiveDirectoryIterator($configPath, FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
foreach ($iterator as $file) {
|
||||
/** var SplFileInfo $file */
|
||||
if (\is_dir($file) || $file->getExtension() != 'php' || \in_array($file->getBaseName('.php'), $exclude_file)) {
|
||||
if (is_dir($file) || $file->getExtension() != 'php' || in_array($file->getBaseName('.php'), $excludeFile)) {
|
||||
continue;
|
||||
}
|
||||
$app_config_file = $file->getPath() . '/app.php';
|
||||
if (!\is_file($app_config_file)) {
|
||||
$appConfigFile = $file->getPath() . '/app.php';
|
||||
if (!is_file($appConfigFile)) {
|
||||
continue;
|
||||
}
|
||||
$relative_path = \str_replace($config_path . DIRECTORY_SEPARATOR, '', substr($file, 0, -4));
|
||||
$explode = \array_reverse(\explode(DIRECTORY_SEPARATOR, $relative_path));
|
||||
if (\count($explode) >= 2) {
|
||||
$app_config = include $app_config_file;
|
||||
if (empty($app_config['enable'])) {
|
||||
$relativePath = str_replace($configPath . DIRECTORY_SEPARATOR, '', substr($file, 0, -4));
|
||||
$explode = array_reverse(explode(DIRECTORY_SEPARATOR, $relativePath));
|
||||
if (count($explode) >= 2) {
|
||||
$appConfig = include $appConfigFile;
|
||||
if (empty($appConfig['enable'])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -193,12 +210,13 @@ class Config
|
||||
$tmp[$section] = $config;
|
||||
$config = $tmp;
|
||||
}
|
||||
$all_config = \array_replace_recursive($all_config, $config);
|
||||
$allConfig = array_replace_recursive($allConfig, $config);
|
||||
}
|
||||
return $all_config;
|
||||
return $allConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get.
|
||||
* @param string|null $key
|
||||
* @param mixed $default
|
||||
* @return array|mixed|void|null
|
||||
@@ -206,46 +224,47 @@ class Config
|
||||
public static function get(string $key = null, $default = null)
|
||||
{
|
||||
if ($key === null) {
|
||||
return static::$_config;
|
||||
return static::$config;
|
||||
}
|
||||
$key_array = \explode('.', $key);
|
||||
$value = static::$_config;
|
||||
$finded = true;
|
||||
foreach ($key_array as $index) {
|
||||
$keyArray = explode('.', $key);
|
||||
$value = static::$config;
|
||||
$found = true;
|
||||
foreach ($keyArray as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
if (static::$_loaded) {
|
||||
if (static::$loaded) {
|
||||
return $default;
|
||||
}
|
||||
$finded = false;
|
||||
$found = false;
|
||||
break;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
if ($finded) {
|
||||
if ($found) {
|
||||
return $value;
|
||||
}
|
||||
return static::read($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read.
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
protected static function read(string $key, $default = null)
|
||||
{
|
||||
$path = static::$_configPath;
|
||||
$path = static::$configPath;
|
||||
if ($path === '') {
|
||||
return $default;
|
||||
}
|
||||
$keys = $key_array = \explode('.', $key);
|
||||
foreach ($key_array as $index => $section) {
|
||||
$keys = $keyArray = explode('.', $key);
|
||||
foreach ($keyArray as $index => $section) {
|
||||
unset($keys[$index]);
|
||||
if (\is_file($file = "$path/$section.php")) {
|
||||
if (is_file($file = "$path/$section.php")) {
|
||||
$config = include $file;
|
||||
return static::find($keys, $config, $default);
|
||||
}
|
||||
if (!\is_dir($path = "$path/$section")) {
|
||||
if (!is_dir($path = "$path/$section")) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
@@ -253,18 +272,19 @@ class Config
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $key_array
|
||||
* Find.
|
||||
* @param array $keyArray
|
||||
* @param mixed $stack
|
||||
* @param mixed $default
|
||||
* @return array|mixed
|
||||
*/
|
||||
protected static function find(array $key_array, $stack, $default)
|
||||
protected static function find(array $keyArray, $stack, $default)
|
||||
{
|
||||
if (!\is_array($stack)) {
|
||||
if (!is_array($stack)) {
|
||||
return $default;
|
||||
}
|
||||
$value = $stack;
|
||||
foreach ($key_array as $index) {
|
||||
foreach ($keyArray as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace Webman;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Webman\Exception\NotFoundException;
|
||||
use function array_key_exists;
|
||||
use function class_exists;
|
||||
|
||||
/**
|
||||
* Class Container
|
||||
@@ -15,43 +17,46 @@ class Container implements ContainerInterface
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_instances = [];
|
||||
protected $instances = [];
|
||||
/**
|
||||
* @var array
|
||||
* @var array
|
||||
*/
|
||||
protected $_definitions = [];
|
||||
protected $definitions = [];
|
||||
|
||||
/**
|
||||
* Get.
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function get(string $name)
|
||||
{
|
||||
if (!isset($this->_instances[$name])) {
|
||||
if (isset($this->_definitions[$name])) {
|
||||
$this->_instances[$name] = call_user_func($this->_definitions[$name], $this);
|
||||
if (!isset($this->instances[$name])) {
|
||||
if (isset($this->definitions[$name])) {
|
||||
$this->instances[$name] = call_user_func($this->definitions[$name], $this);
|
||||
} else {
|
||||
if (!\class_exists($name)) {
|
||||
if (!class_exists($name)) {
|
||||
throw new NotFoundException("Class '$name' not found");
|
||||
}
|
||||
$this->_instances[$name] = new $name();
|
||||
$this->instances[$name] = new $name();
|
||||
}
|
||||
}
|
||||
return $this->_instances[$name];
|
||||
return $this->instances[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Has.
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function has(string $name): bool
|
||||
{
|
||||
return \array_key_exists($name, $this->_instances)
|
||||
|| array_key_exists($name, $this->_definitions);
|
||||
return array_key_exists($name, $this->instances)
|
||||
|| array_key_exists($name, $this->definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make.
|
||||
* @param string $name
|
||||
* @param array $constructor
|
||||
* @return mixed
|
||||
@@ -59,19 +64,20 @@ class Container implements ContainerInterface
|
||||
*/
|
||||
public function make(string $name, array $constructor = [])
|
||||
{
|
||||
if (!\class_exists($name)) {
|
||||
if (!class_exists($name)) {
|
||||
throw new NotFoundException("Class '$name' not found");
|
||||
}
|
||||
return new $name(... array_values($constructor));
|
||||
}
|
||||
|
||||
/**
|
||||
* AddDefinitions.
|
||||
* @param array $definitions
|
||||
* @return $this
|
||||
*/
|
||||
public function addDefinitions(array $definitions)
|
||||
public function addDefinitions(array $definitions): Container
|
||||
{
|
||||
$this->_definitions = array_merge($this->_definitions, $definitions);
|
||||
$this->definitions = array_merge($this->definitions, $definitions);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
129
vendor/workerman/webman-framework/src/Context.php
vendored
Normal file
129
vendor/workerman/webman-framework/src/Context.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Webman;
|
||||
|
||||
use Fiber;
|
||||
use SplObjectStorage;
|
||||
use StdClass;
|
||||
use Swow\Coroutine;
|
||||
use WeakMap;
|
||||
use Workerman\Events\Revolt;
|
||||
use Workerman\Events\Swoole;
|
||||
use Workerman\Events\Swow;
|
||||
use Workerman\Worker;
|
||||
use function property_exists;
|
||||
|
||||
/**
|
||||
* Class Context
|
||||
* @package Webman
|
||||
*/
|
||||
class Context
|
||||
{
|
||||
|
||||
/**
|
||||
* @var SplObjectStorage|WeakMap
|
||||
*/
|
||||
protected static $objectStorage;
|
||||
|
||||
/**
|
||||
* @var StdClass
|
||||
*/
|
||||
protected static $object;
|
||||
|
||||
/**
|
||||
* @return StdClass
|
||||
*/
|
||||
protected static function getObject(): StdClass
|
||||
{
|
||||
if (!static::$objectStorage) {
|
||||
static::$objectStorage = class_exists(WeakMap::class) ? new WeakMap() : new SplObjectStorage();
|
||||
static::$object = new StdClass;
|
||||
}
|
||||
$key = static::getKey();
|
||||
if (!isset(static::$objectStorage[$key])) {
|
||||
static::$objectStorage[$key] = new StdClass;
|
||||
}
|
||||
return static::$objectStorage[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
protected static function getKey()
|
||||
{
|
||||
switch (Worker::$eventLoopClass) {
|
||||
case Revolt::class:
|
||||
return Fiber::getCurrent();
|
||||
case Swoole::class:
|
||||
return \Swoole\Coroutine::getContext();
|
||||
case Swow::class:
|
||||
return Coroutine::getCurrent();
|
||||
}
|
||||
return static::$object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $key
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get(string $key = null)
|
||||
{
|
||||
$obj = static::getObject();
|
||||
if ($key === null) {
|
||||
return $obj;
|
||||
}
|
||||
return $obj->$key ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public static function set(string $key, $value): void
|
||||
{
|
||||
$obj = static::getObject();
|
||||
$obj->$key = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
public static function delete(string $key): void
|
||||
{
|
||||
$obj = static::getObject();
|
||||
unset($obj->$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public static function has(string $key): bool
|
||||
{
|
||||
$obj = static::getObject();
|
||||
return property_exists($obj, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function destroy(): void
|
||||
{
|
||||
unset(static::$objectStorage[static::getKey()]);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,9 @@ use Psr\Log\LoggerInterface;
|
||||
use Throwable;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use function json_encode;
|
||||
use function nl2br;
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
* Class Handler
|
||||
@@ -28,12 +31,12 @@ class ExceptionHandler implements ExceptionHandlerInterface
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $_logger = null;
|
||||
protected $logger = null;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $_debug = false;
|
||||
protected $debug = false;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
@@ -47,8 +50,8 @@ class ExceptionHandler implements ExceptionHandlerInterface
|
||||
*/
|
||||
public function __construct($logger, $debug)
|
||||
{
|
||||
$this->_logger = $logger;
|
||||
$this->_debug = $debug;
|
||||
$this->logger = $logger;
|
||||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,9 +65,9 @@ class ExceptionHandler implements ExceptionHandlerInterface
|
||||
}
|
||||
$logs = '';
|
||||
if ($request = \request()) {
|
||||
$logs = $request->getRealIp() . ' ' . $request->method() . ' ' . \trim($request->fullUrl(), '/');
|
||||
$logs = $request->getRealIp() . ' ' . $request->method() . ' ' . trim($request->fullUrl(), '/');
|
||||
}
|
||||
$this->_logger->error($logs . PHP_EOL . $exception);
|
||||
$this->logger->error($logs . PHP_EOL . $exception);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,12 +79,12 @@ class ExceptionHandler implements ExceptionHandlerInterface
|
||||
{
|
||||
$code = $exception->getCode();
|
||||
if ($request->expectsJson()) {
|
||||
$json = ['code' => $code ? $code : 500, 'msg' => $this->_debug ? $exception->getMessage() : 'Server internal error'];
|
||||
$this->_debug && $json['traces'] = (string)$exception;
|
||||
$json = ['code' => $code ?: 500, 'msg' => $this->debug ? $exception->getMessage() : 'Server internal error'];
|
||||
$this->debug && $json['traces'] = (string)$exception;
|
||||
return new Response(200, ['Content-Type' => 'application/json'],
|
||||
\json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
$error = $this->_debug ? \nl2br((string)$exception) : 'Server internal error';
|
||||
$error = $this->debug ? nl2br((string)$exception) : 'Server internal error';
|
||||
return new Response(500, [], $error);
|
||||
}
|
||||
|
||||
@@ -89,7 +92,7 @@ class ExceptionHandler implements ExceptionHandlerInterface
|
||||
* @param Throwable $e
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldntReport(Throwable $e)
|
||||
protected function shouldntReport(Throwable $e): bool
|
||||
{
|
||||
foreach ($this->dontReport as $type) {
|
||||
if ($e instanceof $type) {
|
||||
@@ -98,4 +101,18 @@ class ExceptionHandler implements ExceptionHandlerInterface
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatible $this->_debug
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool|null
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
if ($name === '_debug') {
|
||||
return $this->debug;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,15 @@ use Webman\Http\Response;
|
||||
interface ExceptionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @param Throwable $e
|
||||
* @param Throwable $exception
|
||||
* @return mixed
|
||||
*/
|
||||
public function report(Throwable $e);
|
||||
public function report(Throwable $exception);
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Throwable $e
|
||||
* @param Throwable $exception
|
||||
* @return Response
|
||||
*/
|
||||
public function render(Request $request, Throwable $e): Response;
|
||||
public function render(Request $request, Throwable $exception): Response;
|
||||
}
|
||||
33
vendor/workerman/webman-framework/src/File.php
vendored
33
vendor/workerman/webman-framework/src/File.php
vendored
@@ -14,31 +14,42 @@
|
||||
|
||||
namespace Webman;
|
||||
|
||||
use SplFileInfo;
|
||||
use Webman\Exception\FileException;
|
||||
use function chmod;
|
||||
use function is_dir;
|
||||
use function mkdir;
|
||||
use function pathinfo;
|
||||
use function restore_error_handler;
|
||||
use function set_error_handler;
|
||||
use function sprintf;
|
||||
use function strip_tags;
|
||||
use function umask;
|
||||
|
||||
class File extends \SplFileInfo
|
||||
class File extends SplFileInfo
|
||||
{
|
||||
|
||||
/**
|
||||
* Move.
|
||||
* @param string $destination
|
||||
* @return File
|
||||
*/
|
||||
public function move(string $destination)
|
||||
public function move(string $destination): File
|
||||
{
|
||||
\set_error_handler(function ($type, $msg) use (&$error) {
|
||||
set_error_handler(function ($type, $msg) use (&$error) {
|
||||
$error = $msg;
|
||||
});
|
||||
$path = \pathinfo($destination, PATHINFO_DIRNAME);
|
||||
if (!\is_dir($path) && !\mkdir($path, 0777, true)) {
|
||||
\restore_error_handler();
|
||||
throw new FileException(\sprintf('Unable to create the "%s" directory (%s)', $path, \strip_tags($error)));
|
||||
$path = pathinfo($destination, PATHINFO_DIRNAME);
|
||||
if (!is_dir($path) && !mkdir($path, 0777, true)) {
|
||||
restore_error_handler();
|
||||
throw new FileException(sprintf('Unable to create the "%s" directory (%s)', $path, strip_tags($error)));
|
||||
}
|
||||
if (!rename($this->getPathname(), $destination)) {
|
||||
\restore_error_handler();
|
||||
throw new FileException(\sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $destination, \strip_tags($error)));
|
||||
restore_error_handler();
|
||||
throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $destination, strip_tags($error)));
|
||||
}
|
||||
\restore_error_handler();
|
||||
@\chmod($destination, 0666 & ~\umask());
|
||||
restore_error_handler();
|
||||
@chmod($destination, 0666 & ~umask());
|
||||
return new self($destination);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,16 @@
|
||||
|
||||
namespace Webman\Http;
|
||||
|
||||
use Webman\App;
|
||||
use Webman\Route\Route;
|
||||
use function current;
|
||||
use function filter_var;
|
||||
use function ip2long;
|
||||
use function is_array;
|
||||
use function strpos;
|
||||
use const FILTER_FLAG_IPV4;
|
||||
use const FILTER_FLAG_NO_PRIV_RANGE;
|
||||
use const FILTER_FLAG_NO_RES_RANGE;
|
||||
use const FILTER_VALIDATE_IP;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
@@ -57,25 +65,27 @@ class Request extends \Workerman\Protocols\Http\Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Input
|
||||
* @param string $name
|
||||
* @param string|null $default
|
||||
* @param mixed $default
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function input($name, $default = null)
|
||||
public function input(string $name, $default = null)
|
||||
{
|
||||
$post = $this->post();
|
||||
if (isset($post[$name])) {
|
||||
return $post[$name];
|
||||
}
|
||||
$get = $this->get();
|
||||
return isset($get[$name]) ? $get[$name] : $default;
|
||||
return $get[$name] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
public function only(array $keys)
|
||||
public function only(array $keys): array
|
||||
{
|
||||
$all = $this->all();
|
||||
$result = [];
|
||||
@@ -88,6 +98,7 @@ class Request extends \Workerman\Protocols\Http\Request
|
||||
}
|
||||
|
||||
/**
|
||||
* Except
|
||||
* @param array $keys
|
||||
* @return mixed|null
|
||||
*/
|
||||
@@ -101,6 +112,7 @@ class Request extends \Workerman\Protocols\Http\Request
|
||||
}
|
||||
|
||||
/**
|
||||
* File
|
||||
* @param string|null $name
|
||||
* @return null|UploadFile[]|UploadFile
|
||||
*/
|
||||
@@ -112,164 +124,179 @@ class Request extends \Workerman\Protocols\Http\Request
|
||||
}
|
||||
if ($name !== null) {
|
||||
// Multi files
|
||||
if (\is_array(\current($files))) {
|
||||
if (is_array(current($files))) {
|
||||
return $this->parseFiles($files);
|
||||
}
|
||||
return $this->parseFile($files);
|
||||
}
|
||||
$upload_files = [];
|
||||
$uploadFiles = [];
|
||||
foreach ($files as $name => $file) {
|
||||
// Multi files
|
||||
if (\is_array(\current($file))) {
|
||||
$upload_files[$name] = $this->parseFiles($file);
|
||||
if (is_array(current($file))) {
|
||||
$uploadFiles[$name] = $this->parseFiles($file);
|
||||
} else {
|
||||
$upload_files[$name] = $this->parseFile($file);
|
||||
$uploadFiles[$name] = $this->parseFile($file);
|
||||
}
|
||||
}
|
||||
return $upload_files;
|
||||
return $uploadFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* ParseFile
|
||||
* @param array $file
|
||||
* @return UploadFile
|
||||
*/
|
||||
protected function parseFile(array $file)
|
||||
protected function parseFile(array $file): UploadFile
|
||||
{
|
||||
return new UploadFile($file['tmp_name'], $file['name'], $file['type'], $file['error']);
|
||||
}
|
||||
|
||||
/**
|
||||
* ParseFiles
|
||||
* @param array $files
|
||||
* @return array
|
||||
*/
|
||||
protected function parseFiles(array $files)
|
||||
protected function parseFiles(array $files): array
|
||||
{
|
||||
$upload_files = [];
|
||||
$uploadFiles = [];
|
||||
foreach ($files as $key => $file) {
|
||||
if (\is_array(\current($file))) {
|
||||
$upload_files[$key] = $this->parseFiles($file);
|
||||
if (is_array(current($file))) {
|
||||
$uploadFiles[$key] = $this->parseFiles($file);
|
||||
} else {
|
||||
$upload_files[$key] = $this->parseFile($file);
|
||||
$uploadFiles[$key] = $this->parseFile($file);
|
||||
}
|
||||
}
|
||||
return $upload_files;
|
||||
return $uploadFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetRemoteIp
|
||||
* @return string
|
||||
*/
|
||||
public function getRemoteIp()
|
||||
public function getRemoteIp(): string
|
||||
{
|
||||
return App::connection()->getRemoteIp();
|
||||
return $this->connection->getRemoteIp();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetRemotePort
|
||||
* @return int
|
||||
*/
|
||||
public function getRemotePort()
|
||||
public function getRemotePort(): int
|
||||
{
|
||||
return App::connection()->getRemotePort();
|
||||
return $this->connection->getRemotePort();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetLocalIp
|
||||
* @return string
|
||||
*/
|
||||
public function getLocalIp()
|
||||
public function getLocalIp(): string
|
||||
{
|
||||
return App::connection()->getLocalIp();
|
||||
return $this->connection->getLocalIp();
|
||||
}
|
||||
|
||||
/**
|
||||
* GetLocalPort
|
||||
* @return int
|
||||
*/
|
||||
public function getLocalPort()
|
||||
public function getLocalPort(): int
|
||||
{
|
||||
return App::connection()->getLocalPort();
|
||||
return $this->connection->getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $safe_mode
|
||||
* GetRealIp
|
||||
* @param bool $safeMode
|
||||
* @return string
|
||||
*/
|
||||
public function getRealIp(bool $safe_mode = true)
|
||||
public function getRealIp(bool $safeMode = true): string
|
||||
{
|
||||
$remote_ip = $this->getRemoteIp();
|
||||
if ($safe_mode && !static::isIntranetIp($remote_ip)) {
|
||||
return $remote_ip;
|
||||
$remoteIp = $this->getRemoteIp();
|
||||
if ($safeMode && !static::isIntranetIp($remoteIp)) {
|
||||
return $remoteIp;
|
||||
}
|
||||
return $this->header('client-ip', $this->header('x-forwarded-for',
|
||||
$this->header('x-real-ip', $this->header('x-client-ip',
|
||||
$this->header('via', $remote_ip)))));
|
||||
$ip = $this->header('x-real-ip', $this->header('x-forwarded-for',
|
||||
$this->header('client-ip', $this->header('x-client-ip',
|
||||
$this->header('via', $remoteIp)))));
|
||||
return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : $remoteIp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Url
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
public function url(): string
|
||||
{
|
||||
return '//' . $this->host() . $this->path();
|
||||
}
|
||||
|
||||
/**
|
||||
* FullUrl
|
||||
* @return string
|
||||
*/
|
||||
public function fullUrl()
|
||||
public function fullUrl(): string
|
||||
{
|
||||
return '//' . $this->host() . $this->uri();
|
||||
}
|
||||
|
||||
/**
|
||||
* IsAjax
|
||||
* @return bool
|
||||
*/
|
||||
public function isAjax()
|
||||
public function isAjax(): bool
|
||||
{
|
||||
return $this->header('X-Requested-With') === 'XMLHttpRequest';
|
||||
}
|
||||
|
||||
/**
|
||||
* IsPjax
|
||||
* @return bool
|
||||
*/
|
||||
public function isPjax()
|
||||
public function isPjax(): bool
|
||||
{
|
||||
return (bool)$this->header('X-PJAX');
|
||||
}
|
||||
|
||||
/**
|
||||
* ExpectsJson
|
||||
* @return bool
|
||||
*/
|
||||
public function expectsJson()
|
||||
public function expectsJson(): bool
|
||||
{
|
||||
return ($this->isAjax() && !$this->isPjax()) || $this->acceptJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* AcceptJson
|
||||
* @return bool
|
||||
*/
|
||||
public function acceptJson()
|
||||
public function acceptJson(): bool
|
||||
{
|
||||
return false !== \strpos($this->header('accept', ''), 'json');
|
||||
return false !== strpos($this->header('accept', ''), 'json');
|
||||
}
|
||||
|
||||
/**
|
||||
* IsIntranetIp
|
||||
* @param string $ip
|
||||
* @return bool
|
||||
*/
|
||||
public static function isIntranetIp(string $ip)
|
||||
public static function isIntranetIp(string $ip): bool
|
||||
{
|
||||
// Not validate ip .
|
||||
if (!\filter_var($ip, \FILTER_VALIDATE_IP)) {
|
||||
if (!filter_var($ip, FILTER_VALIDATE_IP)) {
|
||||
return false;
|
||||
}
|
||||
// Is intranet ip ? For IPv4, the result of false may not be accurate, so we need to check it manually later .
|
||||
if (!\filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_NO_PRIV_RANGE | \FILTER_FLAG_NO_RES_RANGE)) {
|
||||
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
return true;
|
||||
}
|
||||
// Manual check only for IPv4 .
|
||||
if (!\filter_var($ip, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) {
|
||||
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
|
||||
return false;
|
||||
}
|
||||
// Manual check .
|
||||
$reserved_ips = [
|
||||
$reservedIps = [
|
||||
1681915904 => 1686110207, // 100.64.0.0 - 100.127.255.255
|
||||
3221225472 => 3221225727, // 192.0.0.0 - 192.0.0.255
|
||||
3221225984 => 3221226239, // 192.0.2.0 - 192.0.2.255
|
||||
@@ -279,9 +306,9 @@ class Request extends \Workerman\Protocols\Http\Request
|
||||
3405803776 => 3405804031, // 203.0.113.0 - 203.0.113.255
|
||||
3758096384 => 4026531839, // 224.0.0.0 - 239.255.255.255
|
||||
];
|
||||
$ip_long = \ip2long($ip);
|
||||
foreach ($reserved_ips as $ip_start => $ip_end) {
|
||||
if (($ip_long >= $ip_start) && ($ip_long <= $ip_end)) {
|
||||
$ipLong = ip2long($ip);
|
||||
foreach ($reservedIps as $ipStart => $ipEnd) {
|
||||
if (($ipLong >= $ipStart) && ($ipLong <= $ipEnd)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@
|
||||
|
||||
namespace Webman\Http;
|
||||
|
||||
use Webman\App;
|
||||
use Throwable;
|
||||
use Webman\App;
|
||||
use function filemtime;
|
||||
use function gmdate;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
@@ -26,13 +28,14 @@ class Response extends \Workerman\Protocols\Http\Response
|
||||
/**
|
||||
* @var Throwable
|
||||
*/
|
||||
protected $_exception = null;
|
||||
protected $exception = null;
|
||||
|
||||
/**
|
||||
* File
|
||||
* @param string $file
|
||||
* @return $this
|
||||
*/
|
||||
public function file(string $file)
|
||||
public function file(string $file): Response
|
||||
{
|
||||
if ($this->notModifiedSince($file)) {
|
||||
return $this->withStatus(304);
|
||||
@@ -41,41 +44,44 @@ class Response extends \Workerman\Protocols\Http\Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Download
|
||||
* @param string $file
|
||||
* @param string $download_name
|
||||
* @param string $downloadName
|
||||
* @return $this
|
||||
*/
|
||||
public function download(string $file, string $download_name = '')
|
||||
public function download(string $file, string $downloadName = ''): Response
|
||||
{
|
||||
$this->withFile($file);
|
||||
if ($download_name) {
|
||||
$this->header('Content-Disposition', "attachment; filename=\"$download_name\"");
|
||||
if ($downloadName) {
|
||||
$this->header('Content-Disposition', "attachment; filename=\"$downloadName\"");
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* NotModifiedSince
|
||||
* @param string $file
|
||||
* @return bool
|
||||
*/
|
||||
protected function notModifiedSince(string $file)
|
||||
protected function notModifiedSince(string $file): bool
|
||||
{
|
||||
$if_modified_since = App::request()->header('if-modified-since');
|
||||
if ($if_modified_since === null || !($mtime = \filemtime($file))) {
|
||||
$ifModifiedSince = App::request()->header('if-modified-since');
|
||||
if ($ifModifiedSince === null || !($mtime = filemtime($file))) {
|
||||
return false;
|
||||
}
|
||||
return $if_modified_since === \gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
|
||||
return $ifModifiedSince === gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Throwable $exception
|
||||
* @return Throwable
|
||||
* Exception
|
||||
* @param Throwable|null $exception
|
||||
* @return Throwable|null
|
||||
*/
|
||||
public function exception($exception = null)
|
||||
public function exception(Throwable $exception = null): ?Throwable
|
||||
{
|
||||
if ($exception) {
|
||||
$this->_exception = $exception;
|
||||
$this->exception = $exception;
|
||||
}
|
||||
return $this->_exception;
|
||||
return $this->exception;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
namespace Webman\Http;
|
||||
|
||||
use Webman\File;
|
||||
use function pathinfo;
|
||||
|
||||
/**
|
||||
* Class UploadFile
|
||||
@@ -25,80 +26,86 @@ class UploadFile extends File
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_uploadName = null;
|
||||
protected $uploadName = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_uploadMimeType = null;
|
||||
protected $uploadMimeType = null;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $_uploadErrorCode = null;
|
||||
protected $uploadErrorCode = null;
|
||||
|
||||
/**
|
||||
* UploadFile constructor.
|
||||
*
|
||||
* @param string $file_name
|
||||
* @param string $upload_name
|
||||
* @param string $upload_mime_type
|
||||
* @param int $upload_error_code
|
||||
* @param string $fileName
|
||||
* @param string $uploadName
|
||||
* @param string $uploadMimeType
|
||||
* @param int $uploadErrorCode
|
||||
*/
|
||||
public function __construct(string $file_name, string $upload_name, string $upload_mime_type, int $upload_error_code)
|
||||
public function __construct(string $fileName, string $uploadName, string $uploadMimeType, int $uploadErrorCode)
|
||||
{
|
||||
$this->_uploadName = $upload_name;
|
||||
$this->_uploadMimeType = $upload_mime_type;
|
||||
$this->_uploadErrorCode = $upload_error_code;
|
||||
parent::__construct($file_name);
|
||||
$this->uploadName = $uploadName;
|
||||
$this->uploadMimeType = $uploadMimeType;
|
||||
$this->uploadErrorCode = $uploadErrorCode;
|
||||
parent::__construct($fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetUploadName
|
||||
* @return string
|
||||
*/
|
||||
public function getUploadName()
|
||||
public function getUploadName(): ?string
|
||||
{
|
||||
return $this->_uploadName;
|
||||
return $this->uploadName;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetUploadMimeType
|
||||
* @return string
|
||||
*/
|
||||
public function getUploadMimeType()
|
||||
public function getUploadMimeType(): ?string
|
||||
{
|
||||
return $this->_uploadMimeType;
|
||||
return $this->uploadMimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* GetUploadExtension
|
||||
* @return string
|
||||
*/
|
||||
public function getUploadExtension()
|
||||
public function getUploadExtension(): string
|
||||
{
|
||||
return \pathinfo($this->_uploadName, PATHINFO_EXTENSION);
|
||||
return pathinfo($this->uploadName, PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetUploadErrorCode
|
||||
* @return int
|
||||
*/
|
||||
public function getUploadErrorCode()
|
||||
public function getUploadErrorCode(): ?int
|
||||
{
|
||||
return $this->_uploadErrorCode;
|
||||
return $this->uploadErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* IsValid
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid()
|
||||
public function isValid(): bool
|
||||
{
|
||||
return $this->_uploadErrorCode === UPLOAD_ERR_OK;
|
||||
return $this->uploadErrorCode === UPLOAD_ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* GetUploadMineType
|
||||
* @return string
|
||||
* @deprecated
|
||||
*/
|
||||
public function getUploadMineType()
|
||||
public function getUploadMineType(): ?string
|
||||
{
|
||||
return $this->_uploadMimeType;
|
||||
return $this->uploadMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,23 +35,23 @@ class Install
|
||||
}
|
||||
|
||||
/**
|
||||
* installByRelation
|
||||
* InstallByRelation
|
||||
* @return void
|
||||
*/
|
||||
public static function installByRelation()
|
||||
{
|
||||
foreach (static::$pathRelation as $source => $dest) {
|
||||
if ($pos = strrpos($dest, '/')) {
|
||||
$parent_dir = base_path() . '/' . substr($dest, 0, $pos);
|
||||
if (!is_dir($parent_dir)) {
|
||||
mkdir($parent_dir, 0777, true);
|
||||
$parentDir = base_path() . '/' . substr($dest, 0, $pos);
|
||||
if (!is_dir($parentDir)) {
|
||||
mkdir($parentDir, 0777, true);
|
||||
}
|
||||
}
|
||||
$source_file = __DIR__ . "/$source";
|
||||
copy_dir($source_file, base_path() . "/$dest", true);
|
||||
$sourceFile = __DIR__ . "/$source";
|
||||
copy_dir($sourceFile, base_path() . "/$dest", true);
|
||||
echo "Create $dest\r\n";
|
||||
if (is_file($source_file)) {
|
||||
@unlink($source_file);
|
||||
if (is_file($sourceFile)) {
|
||||
@unlink($sourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<?php
|
||||
|
||||
namespace Webman;
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
@@ -14,34 +11,44 @@ namespace Webman;
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Webman;
|
||||
|
||||
|
||||
use RuntimeException;
|
||||
use function array_merge;
|
||||
use function array_reverse;
|
||||
use function is_array;
|
||||
use function method_exists;
|
||||
|
||||
class Middleware
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_instances = [];
|
||||
protected static $instances = [];
|
||||
|
||||
/**
|
||||
* @param array $all_middlewares
|
||||
* @param mixed $allMiddlewares
|
||||
* @param string $plugin
|
||||
* @return void
|
||||
*/
|
||||
public static function load($all_middlewares, string $plugin = '')
|
||||
public static function load($allMiddlewares, string $plugin = '')
|
||||
{
|
||||
if (!\is_array($all_middlewares)) {
|
||||
if (!is_array($allMiddlewares)) {
|
||||
return;
|
||||
}
|
||||
foreach ($all_middlewares as $app_name => $middlewares) {
|
||||
if (!\is_array($middlewares)) {
|
||||
throw new \RuntimeException('Bad middleware config');
|
||||
foreach ($allMiddlewares as $appName => $middlewares) {
|
||||
if (!is_array($middlewares)) {
|
||||
throw new RuntimeException('Bad middleware config');
|
||||
}
|
||||
foreach ($middlewares as $class_name) {
|
||||
if (\method_exists($class_name, 'process')) {
|
||||
static::$_instances[$plugin][$app_name][] = [$class_name, 'process'];
|
||||
foreach ($middlewares as $className) {
|
||||
if (method_exists($className, 'process')) {
|
||||
static::$instances[$plugin][$appName][] = [$className, 'process'];
|
||||
} else {
|
||||
// @todo Log
|
||||
echo "middleware $class_name::process not exsits\n";
|
||||
echo "middleware $className::process not exsits\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,23 +56,23 @@ class Middleware
|
||||
|
||||
/**
|
||||
* @param string $plugin
|
||||
* @param string $app_name
|
||||
* @param bool $with_global_middleware
|
||||
* @param string $appName
|
||||
* @param bool $withGlobalMiddleware
|
||||
* @return array|mixed
|
||||
*/
|
||||
public static function getMiddleware(string $plugin, string $app_name, bool $with_global_middleware = true)
|
||||
public static function getMiddleware(string $plugin, string $appName, bool $withGlobalMiddleware = true)
|
||||
{
|
||||
$global_middleware = $with_global_middleware && isset(static::$_instances[$plugin]['']) ? static::$_instances[$plugin][''] : [];
|
||||
if ($app_name === '') {
|
||||
return \array_reverse($global_middleware);
|
||||
$globalMiddleware = $withGlobalMiddleware && isset(static::$instances[$plugin]['']) ? static::$instances[$plugin][''] : [];
|
||||
if ($appName === '') {
|
||||
return array_reverse($globalMiddleware);
|
||||
}
|
||||
$app_middleware = static::$_instances[$plugin][$app_name] ?? [];
|
||||
return \array_reverse(\array_merge($global_middleware, $app_middleware));
|
||||
$appMiddleware = static::$instances[$plugin][$appName] ?? [];
|
||||
return array_reverse(array_merge($globalMiddleware, $appMiddleware));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return void
|
||||
* @deprecated
|
||||
*/
|
||||
public static function container($_)
|
||||
{
|
||||
|
||||
242
vendor/workerman/webman-framework/src/Route.php
vendored
242
vendor/workerman/webman-framework/src/Route.php
vendored
@@ -16,8 +16,24 @@ namespace Webman;
|
||||
|
||||
use FastRoute\Dispatcher\GroupCountBased;
|
||||
use FastRoute\RouteCollector;
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use Webman\Route\Route as RouteObject;
|
||||
use function array_diff;
|
||||
use function array_values;
|
||||
use function class_exists;
|
||||
use function explode;
|
||||
use function FastRoute\simpleDispatcher;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_callable;
|
||||
use function is_file;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function method_exists;
|
||||
use function strpos;
|
||||
|
||||
/**
|
||||
* Class Route
|
||||
@@ -28,124 +44,124 @@ class Route
|
||||
/**
|
||||
* @var Route
|
||||
*/
|
||||
protected static $_instance = null;
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* @var GroupCountBased
|
||||
*/
|
||||
protected static $_dispatcher = null;
|
||||
protected static $dispatcher = null;
|
||||
|
||||
/**
|
||||
* @var RouteCollector
|
||||
*/
|
||||
protected static $_collector = null;
|
||||
protected static $collector = null;
|
||||
|
||||
/**
|
||||
* @var null|callable
|
||||
*/
|
||||
protected static $_fallback = null;
|
||||
protected static $fallback = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_nameList = [];
|
||||
protected static $nameList = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected static $_groupPrefix = '';
|
||||
protected static $groupPrefix = '';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected static $_disableDefaultRoute = [];
|
||||
protected static $disableDefaultRoute = [];
|
||||
|
||||
/**
|
||||
* @var RouteObject[]
|
||||
*/
|
||||
protected static $_allRoutes = [];
|
||||
protected static $allRoutes = [];
|
||||
|
||||
/**
|
||||
* @var RouteObject[]
|
||||
*/
|
||||
protected $_routes = [];
|
||||
protected $routes = [];
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function get(string $path, $callback)
|
||||
public static function get(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('GET', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function post(string $path, $callback)
|
||||
public static function post(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('POST', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function put(string $path, $callback)
|
||||
public static function put(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('PUT', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function patch(string $path, $callback)
|
||||
public static function patch(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('PATCH', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function delete(string $path, $callback)
|
||||
public static function delete(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('DELETE', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function head(string $path, $callback)
|
||||
public static function head(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('HEAD', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function options(string $path, $callback)
|
||||
public static function options(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute('OPTIONS', $path, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function any(string $path, $callback)
|
||||
public static function any(string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $path, $callback);
|
||||
}
|
||||
@@ -153,10 +169,10 @@ class Route
|
||||
/**
|
||||
* @param $method
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
public static function add($method, string $path, $callback)
|
||||
public static function add($method, string $path, $callback): RouteObject
|
||||
{
|
||||
return static::addRoute($method, $path, $callback);
|
||||
}
|
||||
@@ -166,18 +182,18 @@ class Route
|
||||
* @param callable|null $callback
|
||||
* @return static
|
||||
*/
|
||||
public static function group($path, callable $callback = null)
|
||||
public static function group($path, callable $callback = null): Route
|
||||
{
|
||||
if ($callback === null) {
|
||||
$callback = $path;
|
||||
$path = '';
|
||||
}
|
||||
$previous_group_prefix = static::$_groupPrefix;
|
||||
static::$_groupPrefix = $previous_group_prefix . $path;
|
||||
$instance = static::$_instance = new static;
|
||||
static::$_collector->addGroup($path, $callback);
|
||||
static::$_instance = null;
|
||||
static::$_groupPrefix = $previous_group_prefix;
|
||||
$previousGroupPrefix = static::$groupPrefix;
|
||||
static::$groupPrefix = $previousGroupPrefix . $path;
|
||||
$instance = static::$instance = new static;
|
||||
static::$collector->addGroup($path, $callback);
|
||||
static::$instance = null;
|
||||
static::$groupPrefix = $previousGroupPrefix;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
@@ -190,41 +206,41 @@ class Route
|
||||
public static function resource(string $name, string $controller, array $options = [])
|
||||
{
|
||||
$name = trim($name, '/');
|
||||
if (\is_array($options) && !empty($options)) {
|
||||
$diff_options = \array_diff($options, ['index', 'create', 'store', 'update', 'show', 'edit', 'destroy', 'recovery']);
|
||||
if (!empty($diff_options)) {
|
||||
foreach ($diff_options as $action) {
|
||||
static::any("/{$name}/{$action}[/{id}]", [$controller, $action])->name("{$name}.{$action}");
|
||||
if (is_array($options) && !empty($options)) {
|
||||
$diffOptions = array_diff($options, ['index', 'create', 'store', 'update', 'show', 'edit', 'destroy', 'recovery']);
|
||||
if (!empty($diffOptions)) {
|
||||
foreach ($diffOptions as $action) {
|
||||
static::any("/$name/{$action}[/{id}]", [$controller, $action])->name("$name.{$action}");
|
||||
}
|
||||
}
|
||||
// 注册路由 由于顺序不同会导致路由无效 因此不适用循环注册
|
||||
if (\in_array('index', $options)) static::get("/{$name}", [$controller, 'index'])->name("{$name}.index");
|
||||
if (\in_array('create', $options)) static::get("/{$name}/create", [$controller, 'create'])->name("{$name}.create");
|
||||
if (\in_array('store', $options)) static::post("/{$name}", [$controller, 'store'])->name("{$name}.store");
|
||||
if (\in_array('update', $options)) static::put("/{$name}/{id}", [$controller, 'update'])->name("{$name}.update");
|
||||
if (\in_array('show', $options)) static::get("/{$name}/{id}", [$controller, 'show'])->name("{$name}.show");
|
||||
if (\in_array('edit', $options)) static::get("/{$name}/{id}/edit", [$controller, 'edit'])->name("{$name}.edit");
|
||||
if (\in_array('destroy', $options)) static::delete("/{$name}/{id}", [$controller, 'destroy'])->name("{$name}.destroy");
|
||||
if (\in_array('recovery', $options)) static::put("/{$name}/{id}/recovery", [$controller, 'recovery'])->name("{$name}.recovery");
|
||||
if (in_array('index', $options)) static::get("/$name", [$controller, 'index'])->name("$name.index");
|
||||
if (in_array('create', $options)) static::get("/$name/create", [$controller, 'create'])->name("$name.create");
|
||||
if (in_array('store', $options)) static::post("/$name", [$controller, 'store'])->name("$name.store");
|
||||
if (in_array('update', $options)) static::put("/$name/{id}", [$controller, 'update'])->name("$name.update");
|
||||
if (in_array('show', $options)) static::get("/$name/{id}", [$controller, 'show'])->name("$name.show");
|
||||
if (in_array('edit', $options)) static::get("/$name/{id}/edit", [$controller, 'edit'])->name("$name.edit");
|
||||
if (in_array('destroy', $options)) static::delete("/$name/{id}", [$controller, 'destroy'])->name("$name.destroy");
|
||||
if (in_array('recovery', $options)) static::put("/$name/{id}/recovery", [$controller, 'recovery'])->name("$name.recovery");
|
||||
} else {
|
||||
//为空时自动注册所有常用路由
|
||||
if (\method_exists($controller, 'index')) static::get("/{$name}", [$controller, 'index'])->name("{$name}.index");
|
||||
if (\method_exists($controller, 'create')) static::get("/{$name}/create", [$controller, 'create'])->name("{$name}.create");
|
||||
if (\method_exists($controller, 'store')) static::post("/{$name}", [$controller, 'store'])->name("{$name}.store");
|
||||
if (\method_exists($controller, 'update')) static::put("/{$name}/{id}", [$controller, 'update'])->name("{$name}.update");
|
||||
if (\method_exists($controller, 'show')) static::get("/{$name}/{id}", [$controller, 'show'])->name("{$name}.show");
|
||||
if (\method_exists($controller, 'edit')) static::get("/{$name}/{id}/edit", [$controller, 'edit'])->name("{$name}.edit");
|
||||
if (\method_exists($controller, 'destroy')) static::delete("/{$name}/{id}", [$controller, 'destroy'])->name("{$name}.destroy");
|
||||
if (\method_exists($controller, 'recovery')) static::put("/{$name}/{id}/recovery", [$controller, 'recovery'])->name("{$name}.recovery");
|
||||
if (method_exists($controller, 'index')) static::get("/$name", [$controller, 'index'])->name("$name.index");
|
||||
if (method_exists($controller, 'create')) static::get("/$name/create", [$controller, 'create'])->name("$name.create");
|
||||
if (method_exists($controller, 'store')) static::post("/$name", [$controller, 'store'])->name("$name.store");
|
||||
if (method_exists($controller, 'update')) static::put("/$name/{id}", [$controller, 'update'])->name("$name.update");
|
||||
if (method_exists($controller, 'show')) static::get("/$name/{id}", [$controller, 'show'])->name("$name.show");
|
||||
if (method_exists($controller, 'edit')) static::get("/$name/{id}/edit", [$controller, 'edit'])->name("$name.edit");
|
||||
if (method_exists($controller, 'destroy')) static::delete("/$name/{id}", [$controller, 'destroy'])->name("$name.destroy");
|
||||
if (method_exists($controller, 'recovery')) static::put("/$name/{id}/recovery", [$controller, 'recovery'])->name("$name.recovery");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RouteObject[]
|
||||
*/
|
||||
public static function getRoutes()
|
||||
public static function getRoutes(): array
|
||||
{
|
||||
return static::$_allRoutes;
|
||||
return static::$allRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,26 +250,28 @@ class Route
|
||||
*/
|
||||
public static function disableDefaultRoute($plugin = '')
|
||||
{
|
||||
static::$_disableDefaultRoute[$plugin] = true;
|
||||
static::$disableDefaultRoute[$plugin] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $plugin
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasDisableDefaultRoute($plugin = '')
|
||||
public static function hasDisableDefaultRoute(string $plugin = ''): bool
|
||||
{
|
||||
return static::$_disableDefaultRoute[$plugin] ?? false;
|
||||
return static::$disableDefaultRoute[$plugin] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $middleware
|
||||
* @return $this
|
||||
*/
|
||||
public function middleware($middleware)
|
||||
public function middleware($middleware): Route
|
||||
{
|
||||
foreach ($this->_routes as $route) {
|
||||
foreach ($this->routes as $route) {
|
||||
$route->middleware($middleware);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,25 +279,25 @@ class Route
|
||||
*/
|
||||
public function collect(RouteObject $route)
|
||||
{
|
||||
$this->_routes[] = $route;
|
||||
$this->routes[] = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param string $name
|
||||
* @param RouteObject $instance
|
||||
*/
|
||||
public static function setByName(string $name, RouteObject $instance)
|
||||
{
|
||||
static::$_nameList[$name] = $instance;
|
||||
static::$nameList[$name] = $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param string $name
|
||||
* @return null|RouteObject
|
||||
*/
|
||||
public static function getByName(string $name)
|
||||
public static function getByName(string $name): ?RouteObject
|
||||
{
|
||||
return static::$_nameList[$name] ?? null;
|
||||
return static::$nameList[$name] ?? null;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,32 +306,32 @@ class Route
|
||||
* @param string $path
|
||||
* @return array
|
||||
*/
|
||||
public static function dispatch($method, string $path)
|
||||
public static function dispatch(string $method, string $path): array
|
||||
{
|
||||
return static::$_dispatcher->dispatch($method, $path);
|
||||
return static::$dispatcher->dispatch($method, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return callable|false|string[]
|
||||
*/
|
||||
public static function convertToCallable(string $path, $callback)
|
||||
{
|
||||
if (\is_string($callback) && \strpos($callback, '@')) {
|
||||
$callback = \explode('@', $callback, 2);
|
||||
if (is_string($callback) && strpos($callback, '@')) {
|
||||
$callback = explode('@', $callback, 2);
|
||||
}
|
||||
|
||||
if (!\is_array($callback)) {
|
||||
if (!\is_callable($callback)) {
|
||||
$call_str = \is_scalar($callback) ? $callback : 'Closure';
|
||||
echo "Route $path $call_str is not callable\n";
|
||||
if (!is_array($callback)) {
|
||||
if (!is_callable($callback)) {
|
||||
$callStr = is_scalar($callback) ? $callback : 'Closure';
|
||||
echo "Route $path $callStr is not callable\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$callback = \array_values($callback);
|
||||
if (!isset($callback[1]) || !\class_exists($callback[0]) || !\method_exists($callback[0], $callback[1])) {
|
||||
echo "Route $path " . \json_encode($callback) . " is not callable\n";
|
||||
$callback = array_values($callback);
|
||||
if (!isset($callback[1]) || !class_exists($callback[0]) || !method_exists($callback[0], $callback[1])) {
|
||||
echo "Route $path " . json_encode($callback) . " is not callable\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -322,56 +340,57 @@ class Route
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $methods
|
||||
* @param array|string $methods
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
* @param callable|mixed $callback
|
||||
* @return RouteObject
|
||||
*/
|
||||
protected static function addRoute($methods, string $path, $callback)
|
||||
protected static function addRoute($methods, string $path, $callback): RouteObject
|
||||
{
|
||||
$route = new RouteObject($methods, static::$_groupPrefix . $path, $callback);
|
||||
static::$_allRoutes[] = $route;
|
||||
$route = new RouteObject($methods, static::$groupPrefix . $path, $callback);
|
||||
static::$allRoutes[] = $route;
|
||||
|
||||
if ($callback = static::convertToCallable($path, $callback)) {
|
||||
static::$_collector->addRoute($methods, $path, ['callback' => $callback, 'route' => $route]);
|
||||
static::$collector->addRoute($methods, $path, ['callback' => $callback, 'route' => $route]);
|
||||
}
|
||||
if (static::$_instance) {
|
||||
static::$_instance->collect($route);
|
||||
if (static::$instance) {
|
||||
static::$instance->collect($route);
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $paths
|
||||
* Load.
|
||||
* @param mixed $paths
|
||||
* @return void
|
||||
*/
|
||||
public static function load($paths)
|
||||
{
|
||||
if (!\is_array($paths)) {
|
||||
if (!is_array($paths)) {
|
||||
return;
|
||||
}
|
||||
static::$_dispatcher = simpleDispatcher(function (RouteCollector $route) use ($paths) {
|
||||
static::$dispatcher = simpleDispatcher(function (RouteCollector $route) use ($paths) {
|
||||
Route::setCollector($route);
|
||||
foreach ($paths as $config_path) {
|
||||
$route_config_file = $config_path . '/route.php';
|
||||
if (\is_file($route_config_file)) {
|
||||
require_once $route_config_file;
|
||||
foreach ($paths as $configPath) {
|
||||
$routeConfigFile = $configPath . '/route.php';
|
||||
if (is_file($routeConfigFile)) {
|
||||
require_once $routeConfigFile;
|
||||
}
|
||||
if (!is_dir($plugin_config_path = $config_path . '/plugin')) {
|
||||
if (!is_dir($pluginConfigPath = $configPath . '/plugin')) {
|
||||
continue;
|
||||
}
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($plugin_config_path, \FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
$dirIterator = new RecursiveDirectoryIterator($pluginConfigPath, FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->getBaseName('.php') !== 'route') {
|
||||
continue;
|
||||
}
|
||||
$app_config_file = pathinfo($file, PATHINFO_DIRNAME) . '/app.php';
|
||||
if (!is_file($app_config_file)) {
|
||||
$appConfigFile = pathinfo($file, PATHINFO_DIRNAME) . '/app.php';
|
||||
if (!is_file($appConfigFile)) {
|
||||
continue;
|
||||
}
|
||||
$app_config = include $app_config_file;
|
||||
if (empty($app_config['enable'])) {
|
||||
$appConfig = include $appConfigFile;
|
||||
if (empty($appConfig['enable'])) {
|
||||
continue;
|
||||
}
|
||||
require_once $file;
|
||||
@@ -381,34 +400,39 @@ class Route
|
||||
}
|
||||
|
||||
/**
|
||||
* SetCollector.
|
||||
* @param RouteCollector $route
|
||||
* @return void
|
||||
*/
|
||||
public static function setCollector(RouteCollector $route)
|
||||
{
|
||||
static::$_collector = $route;
|
||||
static::$collector = $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callback
|
||||
* Fallback.
|
||||
* @param callable|mixed $callback
|
||||
* @param string $plugin
|
||||
* @return void
|
||||
*/
|
||||
public static function fallback(callable $callback)
|
||||
public static function fallback(callable $callback, string $plugin = '')
|
||||
{
|
||||
static::$_fallback = $callback;
|
||||
static::$fallback[$plugin] = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetFallBack.
|
||||
* @param string $plugin
|
||||
* @return callable|null
|
||||
*/
|
||||
public static function getFallback()
|
||||
public static function getFallback(string $plugin = ''): ?callable
|
||||
{
|
||||
return static::$_fallback;
|
||||
return static::$fallback[$plugin] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return void
|
||||
* @deprecated
|
||||
*/
|
||||
public static function container()
|
||||
{
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
|
||||
namespace Webman\Route;
|
||||
|
||||
use FastRoute\Dispatcher\GroupCountBased;
|
||||
use FastRoute\RouteCollector;
|
||||
use Webman\Route as Router;
|
||||
use function array_merge;
|
||||
use function count;
|
||||
use function preg_replace_callback;
|
||||
use function str_replace;
|
||||
|
||||
/**
|
||||
* Class Route
|
||||
@@ -27,112 +29,119 @@ class Route
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $_name = null;
|
||||
protected $name = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_methods = [];
|
||||
protected $methods = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_path = '';
|
||||
protected $path = '';
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
protected $_callback = null;
|
||||
protected $callback = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_middlewares = [];
|
||||
protected $middlewares = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $_params = [];
|
||||
protected $params = [];
|
||||
|
||||
/**
|
||||
* Route constructor.
|
||||
*
|
||||
* @param array $methods
|
||||
* @param string $path
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function __construct($methods, string $path, $callback)
|
||||
{
|
||||
$this->_methods = (array)$methods;
|
||||
$this->_path = $path;
|
||||
$this->_callback = $callback;
|
||||
$this->methods = (array)$methods;
|
||||
$this->path = $path;
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|null
|
||||
* Get name.
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->_name ?? null;
|
||||
return $this->name ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name.
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function name(string $name)
|
||||
public function name(string $name): Route
|
||||
{
|
||||
$this->_name = $name;
|
||||
$this->name = $name;
|
||||
Router::setByName($name, $this);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware.
|
||||
* @param mixed $middleware
|
||||
* @return $this|array
|
||||
*/
|
||||
public function middleware($middleware = null)
|
||||
{
|
||||
if ($middleware === null) {
|
||||
return $this->_middlewares;
|
||||
return $this->middlewares;
|
||||
}
|
||||
$this->_middlewares = \array_merge($this->_middlewares, (array)$middleware);
|
||||
$this->middlewares = array_merge($this->middlewares, is_array($middleware) ? $middleware : [$middleware]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetPath.
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->_path;
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetMethods.
|
||||
* @return array
|
||||
*/
|
||||
public function getMethods()
|
||||
public function getMethods(): array
|
||||
{
|
||||
return $this->_methods;
|
||||
return $this->methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
* GetCallback.
|
||||
* @return callable|null
|
||||
*/
|
||||
public function getCallback()
|
||||
{
|
||||
return $this->_callback;
|
||||
return $this->callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* GetMiddleware.
|
||||
* @return array
|
||||
*/
|
||||
public function getMiddleware()
|
||||
public function getMiddleware(): array
|
||||
{
|
||||
return $this->_middlewares;
|
||||
return $this->middlewares;
|
||||
}
|
||||
|
||||
/**
|
||||
* Param.
|
||||
* @param string|null $name
|
||||
* @param $default
|
||||
* @return array|mixed|null
|
||||
@@ -140,32 +149,34 @@ class Route
|
||||
public function param(string $name = null, $default = null)
|
||||
{
|
||||
if ($name === null) {
|
||||
return $this->_params;
|
||||
return $this->params;
|
||||
}
|
||||
return $this->_params[$name] ?? $default;
|
||||
return $this->params[$name] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* SetParams.
|
||||
* @param array $params
|
||||
* @return $this
|
||||
*/
|
||||
public function setParams(array $params)
|
||||
public function setParams(array $params): Route
|
||||
{
|
||||
$this->_params = \array_merge($this->_params, $params);
|
||||
$this->params = array_merge($this->params, $params);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $parameters
|
||||
* Url.
|
||||
* @param array $parameters
|
||||
* @return string
|
||||
*/
|
||||
public function url($parameters = [])
|
||||
public function url(array $parameters = []): string
|
||||
{
|
||||
if (empty($parameters)) {
|
||||
return $this->_path;
|
||||
return $this->path;
|
||||
}
|
||||
$path = \str_replace(['[', ']'], '', $this->_path);
|
||||
$path = \preg_replace_callback('/\{(.*?)(?:\:[^\}]*?)*?\}/', function ($matches) use (&$parameters) {
|
||||
$path = str_replace(['[', ']'], '', $this->path);
|
||||
$path = preg_replace_callback('/\{(.*?)(?:\:[^\}]*?)*?\}/', function ($matches) use (&$parameters) {
|
||||
if (!$parameters) {
|
||||
return $matches[0];
|
||||
}
|
||||
@@ -182,7 +193,7 @@ class Route
|
||||
}
|
||||
return $matches[0];
|
||||
}, $path);
|
||||
return \count($parameters) > 0 ? $path . '?' . http_build_query($parameters) : $path;
|
||||
return count($parameters) > 0 ? $path . '?' . http_build_query($parameters) : $path;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
namespace Webman\Session;
|
||||
|
||||
use FastRoute\Dispatcher\GroupCountBased;
|
||||
use FastRoute\RouteCollector;
|
||||
use Workerman\Protocols\Http\Session\FileSessionHandler as FileHandler;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
namespace Webman\Session;
|
||||
|
||||
use FastRoute\Dispatcher\GroupCountBased;
|
||||
use FastRoute\RouteCollector;
|
||||
use Workerman\Protocols\Http\Session\RedisSessionHandler as RedisHandler;
|
||||
|
||||
/**
|
||||
|
||||
18
vendor/workerman/webman-framework/src/Util.php
vendored
18
vendor/workerman/webman-framework/src/Util.php
vendored
@@ -14,6 +14,10 @@
|
||||
|
||||
namespace Webman;
|
||||
|
||||
use function array_diff;
|
||||
use function array_map;
|
||||
use function scandir;
|
||||
|
||||
/**
|
||||
* Class Util
|
||||
* @package Webman
|
||||
@@ -21,17 +25,19 @@ namespace Webman;
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* @param string $path
|
||||
* ScanDir.
|
||||
* @param string $basePath
|
||||
* @param bool $withBasePath
|
||||
* @return array
|
||||
*/
|
||||
public static function scanDir(string $base_path, $with_base_path = true): array
|
||||
public static function scanDir(string $basePath, bool $withBasePath = true): array
|
||||
{
|
||||
if (!is_dir($base_path)) {
|
||||
if (!is_dir($basePath)) {
|
||||
return [];
|
||||
}
|
||||
$paths = \array_diff(\scandir($base_path), array('.', '..')) ?: [];
|
||||
return $with_base_path ? \array_map(function($path) use ($base_path) {
|
||||
return $base_path . DIRECTORY_SEPARATOR . $path;
|
||||
$paths = array_diff(scandir($basePath), array('.', '..')) ?: [];
|
||||
return $withBasePath ? array_map(static function ($path) use ($basePath) {
|
||||
return $basePath . DIRECTORY_SEPARATOR . $path;
|
||||
}, $paths) : $paths;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,11 @@ namespace Webman;
|
||||
interface View
|
||||
{
|
||||
/**
|
||||
* @param $template
|
||||
* @param $vars
|
||||
* @param null $app
|
||||
* Render.
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return string
|
||||
*/
|
||||
static function render(string $template, array $vars, string $app = null);
|
||||
public static function render(string $template, array $vars, string $app = null): string;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,22 @@
|
||||
namespace support;
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use RuntimeException;
|
||||
use Webman\Config;
|
||||
use Webman\Util;
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use Workerman\Protocols\Http;
|
||||
use Workerman\Worker;
|
||||
use function base_path;
|
||||
use function call_user_func;
|
||||
use function is_dir;
|
||||
use function opcache_get_status;
|
||||
use function opcache_invalidate;
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
class App
|
||||
{
|
||||
/**
|
||||
* Run.
|
||||
* @return void
|
||||
*/
|
||||
public static function run()
|
||||
@@ -29,34 +36,34 @@ class App
|
||||
|
||||
static::loadAllConfig(['route', 'container']);
|
||||
|
||||
$error_reporting = config('app.error_reporting');
|
||||
if (isset($error_reporting)) {
|
||||
error_reporting($error_reporting);
|
||||
$errorReporting = config('app.error_reporting');
|
||||
if (isset($errorReporting)) {
|
||||
error_reporting($errorReporting);
|
||||
}
|
||||
if ($timezone = config('app.default_timezone')) {
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
|
||||
$runtime_logs_path = runtime_path() . DIRECTORY_SEPARATOR . 'logs';
|
||||
if (!file_exists($runtime_logs_path) || !is_dir($runtime_logs_path)) {
|
||||
if (!mkdir($runtime_logs_path, 0777, true)) {
|
||||
throw new \RuntimeException("Failed to create runtime logs directory. Please check the permission.");
|
||||
$runtimeLogsPath = runtime_path() . DIRECTORY_SEPARATOR . 'logs';
|
||||
if (!file_exists($runtimeLogsPath) || !is_dir($runtimeLogsPath)) {
|
||||
if (!mkdir($runtimeLogsPath, 0777, true)) {
|
||||
throw new RuntimeException("Failed to create runtime logs directory. Please check the permission.");
|
||||
}
|
||||
}
|
||||
|
||||
$runtime_views_path = runtime_path() . DIRECTORY_SEPARATOR . 'views';
|
||||
if (!file_exists($runtime_views_path) || !is_dir($runtime_views_path)) {
|
||||
if (!mkdir($runtime_views_path, 0777, true)) {
|
||||
throw new \RuntimeException("Failed to create runtime views directory. Please check the permission.");
|
||||
$runtimeViewsPath = runtime_path() . DIRECTORY_SEPARATOR . 'views';
|
||||
if (!file_exists($runtimeViewsPath) || !is_dir($runtimeViewsPath)) {
|
||||
if (!mkdir($runtimeViewsPath, 0777, true)) {
|
||||
throw new RuntimeException("Failed to create runtime views directory. Please check the permission.");
|
||||
}
|
||||
}
|
||||
|
||||
Worker::$onMasterReload = function () {
|
||||
if (function_exists('opcache_get_status')) {
|
||||
if ($status = \opcache_get_status()) {
|
||||
if ($status = opcache_get_status()) {
|
||||
if (isset($status['scripts']) && $scripts = $status['scripts']) {
|
||||
foreach (array_keys($scripts) as $file) {
|
||||
\opcache_invalidate($file, true);
|
||||
opcache_invalidate($file, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,7 +85,7 @@ class App
|
||||
|
||||
if ($config['listen']) {
|
||||
$worker = new Worker($config['listen'], $config['context']);
|
||||
$property_map = [
|
||||
$propertyMap = [
|
||||
'name',
|
||||
'count',
|
||||
'user',
|
||||
@@ -87,36 +94,36 @@ class App
|
||||
'transport',
|
||||
'protocol'
|
||||
];
|
||||
foreach ($property_map as $property) {
|
||||
foreach ($propertyMap as $property) {
|
||||
if (isset($config[$property])) {
|
||||
$worker->$property = $config[$property];
|
||||
}
|
||||
}
|
||||
|
||||
$worker->onWorkerStart = function ($worker) {
|
||||
require_once \base_path() . '/support/bootstrap.php';
|
||||
require_once base_path() . '/support/bootstrap.php';
|
||||
$app = new \Webman\App(config('app.request_class', Request::class), Log::channel('default'), app_path(), public_path());
|
||||
$worker->onMessage = [$app, 'onMessage'];
|
||||
\call_user_func([$app, 'onWorkerStart'], $worker);
|
||||
call_user_func([$app, 'onWorkerStart'], $worker);
|
||||
};
|
||||
}
|
||||
|
||||
// Windows does not support custom processes.
|
||||
if (\DIRECTORY_SEPARATOR === '/') {
|
||||
foreach (config('process', []) as $process_name => $config) {
|
||||
worker_start($process_name, $config);
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
foreach (config('process', []) as $processName => $config) {
|
||||
worker_start($processName, $config);
|
||||
}
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['process'] ?? [] as $process_name => $config) {
|
||||
worker_start("plugin.$firm.$name.$process_name", $config);
|
||||
foreach ($project['process'] ?? [] as $processName => $config) {
|
||||
worker_start("plugin.$firm.$name.$processName", $config);
|
||||
}
|
||||
}
|
||||
foreach ($projects['process'] ?? [] as $process_name => $config) {
|
||||
worker_start("plugin.$firm.$process_name", $config);
|
||||
foreach ($projects['process'] ?? [] as $processName => $config) {
|
||||
worker_start("plugin.$firm.$processName", $config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +132,7 @@ class App
|
||||
}
|
||||
|
||||
/**
|
||||
* LoadAllConfig.
|
||||
* @param array $excludes
|
||||
* @return void
|
||||
*/
|
||||
@@ -134,7 +142,7 @@ class App
|
||||
$directory = base_path() . '/plugin';
|
||||
foreach (Util::scanDir($directory, false) as $name) {
|
||||
$dir = "$directory/$name/config";
|
||||
if (\is_dir($dir)) {
|
||||
if (is_dir($dir)) {
|
||||
Config::load($dir, $excludes, "plugin.$name");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,18 +24,18 @@ class Cache
|
||||
/**
|
||||
* @var Psr16Cache
|
||||
*/
|
||||
public static $_instance = null;
|
||||
public static $instance = null;
|
||||
|
||||
/**
|
||||
* @return Psr16Cache
|
||||
*/
|
||||
public static function instance()
|
||||
{
|
||||
if (!static::$_instance) {
|
||||
if (!static::$instance) {
|
||||
$adapter = new RedisAdapter(Redis::connection()->client());
|
||||
self::$_instance = new Psr16Cache($adapter);
|
||||
self::$instance = new Psr16Cache($adapter);
|
||||
}
|
||||
return static::$_instance;
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
namespace support;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Webman\Config;
|
||||
|
||||
/**
|
||||
@@ -27,7 +26,9 @@ use Webman\Config;
|
||||
class Container
|
||||
{
|
||||
/**
|
||||
* @return ContainerInterface
|
||||
* Instance
|
||||
* @param string $plugin
|
||||
* @return array|mixed|void|null
|
||||
*/
|
||||
public static function instance(string $plugin = '')
|
||||
{
|
||||
|
||||
25
vendor/workerman/webman-framework/src/support/Context.php
vendored
Normal file
25
vendor/workerman/webman-framework/src/support/Context.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Context
|
||||
* @package Webman
|
||||
*/
|
||||
class Context extends \Webman\Context
|
||||
{
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
namespace support;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Database\Capsule\Manager;
|
||||
|
||||
/**
|
||||
@@ -24,7 +25,7 @@ use Illuminate\Database\Capsule\Manager;
|
||||
* @method static int update(string $query, $bindings = [])
|
||||
* @method static int delete(string $query, $bindings = [])
|
||||
* @method static bool statement(string $query, $bindings = [])
|
||||
* @method static mixed transaction(\Closure $callback, $attempts = 1)
|
||||
* @method static mixed transaction(Closure $callback, $attempts = 1)
|
||||
* @method static void beginTransaction()
|
||||
* @method static void rollBack($toLevel = null)
|
||||
* @method static void commit()
|
||||
|
||||
@@ -18,6 +18,9 @@ use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Handler\FormattableHandlerInterface;
|
||||
use Monolog\Handler\HandlerInterface;
|
||||
use Monolog\Logger;
|
||||
use function array_values;
|
||||
use function config;
|
||||
use function is_array;
|
||||
|
||||
/**
|
||||
* Class Log
|
||||
@@ -38,24 +41,26 @@ class Log
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_instance = [];
|
||||
protected static $instance = [];
|
||||
|
||||
/**
|
||||
* Channel.
|
||||
* @param string $name
|
||||
* @return Logger
|
||||
*/
|
||||
public static function channel(string $name = 'default')
|
||||
public static function channel(string $name = 'default'): Logger
|
||||
{
|
||||
if (!isset(static::$_instance[$name])) {
|
||||
$config = \config('log', [])[$name];
|
||||
if (!isset(static::$instance[$name])) {
|
||||
$config = config('log', [])[$name];
|
||||
$handlers = self::handlers($config);
|
||||
$processors = self::processors($config);
|
||||
static::$_instance[$name] = new Logger($name, $handlers, $processors);
|
||||
static::$instance[$name] = new Logger($name, $handlers, $processors);
|
||||
}
|
||||
return static::$_instance[$name];
|
||||
return static::$instance[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handlers.
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
@@ -76,6 +81,7 @@ class Log
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler.
|
||||
* @param string $class
|
||||
* @param array $constructor
|
||||
* @param array $formatterConfig
|
||||
@@ -84,14 +90,14 @@ class Log
|
||||
protected static function handler(string $class, array $constructor, array $formatterConfig): HandlerInterface
|
||||
{
|
||||
/** @var HandlerInterface $handler */
|
||||
$handler = new $class(... \array_values($constructor));
|
||||
$handler = new $class(... array_values($constructor));
|
||||
|
||||
if ($handler instanceof FormattableHandlerInterface && $formatterConfig) {
|
||||
$formatterClass = $formatterConfig['class'];
|
||||
$formatterConstructor = $formatterConfig['constructor'];
|
||||
|
||||
/** @var FormatterInterface $formatter */
|
||||
$formatter = new $formatterClass(... \array_values($formatterConstructor));
|
||||
$formatter = new $formatterClass(... array_values($formatterConstructor));
|
||||
|
||||
$handler->setFormatter($formatter);
|
||||
}
|
||||
@@ -100,6 +106,7 @@ class Log
|
||||
}
|
||||
|
||||
/**
|
||||
* Processors.
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
@@ -111,8 +118,8 @@ class Log
|
||||
}
|
||||
|
||||
foreach ($config['processors'] ?? [] as $value) {
|
||||
if (\is_array($value) && isset($value['class'])) {
|
||||
$value = new $value['class'](... \array_values($value['constructor'] ?? []));;
|
||||
if (is_array($value) && isset($value['class'])) {
|
||||
$value = new $value['class'](... array_values($value['constructor'] ?? []));
|
||||
}
|
||||
$result[] = $value;
|
||||
}
|
||||
@@ -127,6 +134,6 @@ class Log
|
||||
*/
|
||||
public static function __callStatic(string $name, array $arguments)
|
||||
{
|
||||
return static::channel('default')->{$name}(... $arguments);
|
||||
return static::channel()->{$name}(... $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,20 @@
|
||||
|
||||
namespace support;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Pagination\CursorPaginator;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
use Illuminate\Database\Eloquent\Model as BaseModel;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Illuminate\Database\Query\Grammars\Grammar;
|
||||
use Illuminate\Database\Query\Processors\Processor;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
|
||||
/**
|
||||
* @method static \Illuminate\Database\Eloquent\Model make($attributes = [])
|
||||
* @method static BaseModel make($attributes = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withGlobalScope($identifier, $scope)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withoutGlobalScope($scope)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withoutGlobalScopes($scopes = null)
|
||||
@@ -25,53 +35,53 @@ use Illuminate\Database\Eloquent\Model as BaseModel;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder whereKey($id)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder whereKeyNot($id)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder where($column, $operator = null, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Eloquent\Model|null firstWhere($column, $operator = null, $value = null, $boolean = 'and')
|
||||
* @method static BaseModel|null firstWhere($column, $operator = null, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Eloquent\Builder orWhere($column, $operator = null, $value = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder latest($column = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder oldest($column = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Collection hydrate($items)
|
||||
* @method static \Illuminate\Database\Eloquent\Collection fromQuery($query, $bindings = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection[]|null find($id, $columns = [])
|
||||
* @method static BaseModel|\Illuminate\Database\Eloquent\Collection|static[]|static|null find($id, $columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Collection findMany($ids, $columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection[] findOrFail($id, $columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model findOrNew($id, $columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model firstOrNew($attributes = [], $values = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model firstOrCreate($attributes = [], $values = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model updateOrCreate($attributes, $values = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model firstOrFail($columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model|mixed firstOr($columns = [], $callback = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Model sole($columns = [])
|
||||
* @method static BaseModel|\Illuminate\Database\Eloquent\Collection|static|static[] findOrFail($id, $columns = [])
|
||||
* @method static BaseModel|static findOrNew($id, $columns = [])
|
||||
* @method static BaseModel|static firstOrNew($attributes = [], $values = [])
|
||||
* @method static BaseModel|static firstOrCreate($attributes = [], $values = [])
|
||||
* @method static BaseModel|static updateOrCreate($attributes, $values = [])
|
||||
* @method static BaseModel|static firstOrFail($columns = [])
|
||||
* @method static BaseModel|static|mixed firstOr($columns = [], $callback = null)
|
||||
* @method static BaseModel sole($columns = [])
|
||||
* @method static mixed value($column)
|
||||
* @method static \Illuminate\Database\Eloquent\Collection[] get($columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model[][] getModels($columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Collection[]|static[] get($columns = [])
|
||||
* @method static BaseModel[]|static[] getModels($columns = [])
|
||||
* @method static array eagerLoadRelations($models)
|
||||
* @method static \Illuminate\Support\LazyCollection cursor()
|
||||
* @method static \Illuminate\Support\Collection pluck($column, $key = null)
|
||||
* @method static \Illuminate\Contracts\Pagination\LengthAwarePaginator paginate($perPage = null, $columns = [], $pageName = 'page', $page = null)
|
||||
* @method static \Illuminate\Contracts\Pagination\Paginator simplePaginate($perPage = null, $columns = [], $pageName = 'page', $page = null)
|
||||
* @method static \Illuminate\Contracts\Pagination\CursorPaginator cursorPaginate($perPage = null, $columns = [], $cursorName = 'cursor', $cursor = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Model|$this create($attributes = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model|$this forceCreate($attributes)
|
||||
* @method static LazyCollection cursor()
|
||||
* @method static Collection pluck($column, $key = null)
|
||||
* @method static LengthAwarePaginator paginate($perPage = null, $columns = [], $pageName = 'page', $page = null)
|
||||
* @method static Paginator simplePaginate($perPage = null, $columns = [], $pageName = 'page', $page = null)
|
||||
* @method static CursorPaginator cursorPaginate($perPage = null, $columns = [], $cursorName = 'cursor', $cursor = null)
|
||||
* @method static BaseModel|$this create($attributes = [])
|
||||
* @method static BaseModel|$this forceCreate($attributes)
|
||||
* @method static int upsert($values, $uniqueBy, $update = null)
|
||||
* @method static void onDelete($callback)
|
||||
* @method static static|mixed scopes($scopes)
|
||||
* @method static static applyScopes()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder without($relations)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withOnly($relations)
|
||||
* @method static \Illuminate\Database\Eloquent\Model newModelInstance($attributes = [])
|
||||
* @method static BaseModel newModelInstance($attributes = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withCasts($casts)
|
||||
* @method static \Illuminate\Database\Query\Builder getQuery()
|
||||
* @method static Builder getQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder setQuery($query)
|
||||
* @method static \Illuminate\Database\Query\Builder toBase()
|
||||
* @method static Builder toBase()
|
||||
* @method static array getEagerLoads()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder setEagerLoads($eagerLoad)
|
||||
* @method static \Illuminate\Database\Eloquent\Model getModel()
|
||||
* @method static BaseModel getModel()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder setModel($model)
|
||||
* @method static \Closure getMacro($name)
|
||||
* @method static Closure getMacro($name)
|
||||
* @method static bool hasMacro($name)
|
||||
* @method static \Closure getGlobalMacro($name)
|
||||
* @method static Closure getGlobalMacro($name)
|
||||
* @method static bool hasGlobalMacro($name)
|
||||
* @method static static clone()
|
||||
* @method static static clone ()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder has($relation, $operator = '>=', $count = 1, $boolean = 'and', $callback = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder orHas($relation, $operator = '>=', $count = 1)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder doesntHave($relation, $boolean = 'and', $callback = null)
|
||||
@@ -96,116 +106,116 @@ use Illuminate\Database\Eloquent\Model as BaseModel;
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withAvg($relation, $column)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder withExists($relation)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder mergeConstraintsFrom($from)
|
||||
* @method static \Illuminate\Support\Collection explain()
|
||||
* @method static Collection explain()
|
||||
* @method static bool chunk($count, $callback)
|
||||
* @method static \Illuminate\Support\Collection chunkMap($callback, $count = 1000)
|
||||
* @method static Collection chunkMap($callback, $count = 1000)
|
||||
* @method static bool each($callback, $count = 1000)
|
||||
* @method static bool chunkById($count, $callback, $column = null, $alias = null)
|
||||
* @method static bool eachById($callback, $count = 1000, $column = null, $alias = null)
|
||||
* @method static \Illuminate\Support\LazyCollection lazy($chunkSize = 1000)
|
||||
* @method static \Illuminate\Support\LazyCollection lazyById($chunkSize = 1000, $column = null, $alias = null)
|
||||
* @method static \Illuminate\Database\Eloquent\Model|object|null first($columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Model|object|null baseSole($columns = [])
|
||||
* @method static LazyCollection lazy($chunkSize = 1000)
|
||||
* @method static LazyCollection lazyById($chunkSize = 1000, $column = null, $alias = null)
|
||||
* @method static BaseModel|object|static|null first($columns = [])
|
||||
* @method static BaseModel|object|null baseSole($columns = [])
|
||||
* @method static \Illuminate\Database\Eloquent\Builder tap($callback)
|
||||
* @method static mixed when($value, $callback, $default = null)
|
||||
* @method static mixed unless($value, $callback, $default = null)
|
||||
* @method static \Illuminate\Database\Query\Builder select($columns = [])
|
||||
* @method static \Illuminate\Database\Query\Builder selectSub($query, $as)
|
||||
* @method static \Illuminate\Database\Query\Builder selectRaw($expression, $bindings = [])
|
||||
* @method static \Illuminate\Database\Query\Builder fromSub($query, $as)
|
||||
* @method static \Illuminate\Database\Query\Builder fromRaw($expression, $bindings = [])
|
||||
* @method static \Illuminate\Database\Query\Builder addSelect($column)
|
||||
* @method static \Illuminate\Database\Query\Builder distinct()
|
||||
* @method static \Illuminate\Database\Query\Builder from($table, $as = null)
|
||||
* @method static \Illuminate\Database\Query\Builder join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false)
|
||||
* @method static \Illuminate\Database\Query\Builder joinWhere($table, $first, $operator, $second, $type = 'inner')
|
||||
* @method static \Illuminate\Database\Query\Builder joinSub($query, $as, $first, $operator = null, $second = null, $type = 'inner', $where = false)
|
||||
* @method static \Illuminate\Database\Query\Builder leftJoin($table, $first, $operator = null, $second = null)
|
||||
* @method static \Illuminate\Database\Query\Builder leftJoinWhere($table, $first, $operator, $second)
|
||||
* @method static \Illuminate\Database\Query\Builder leftJoinSub($query, $as, $first, $operator = null, $second = null)
|
||||
* @method static \Illuminate\Database\Query\Builder rightJoin($table, $first, $operator = null, $second = null)
|
||||
* @method static \Illuminate\Database\Query\Builder rightJoinWhere($table, $first, $operator, $second)
|
||||
* @method static \Illuminate\Database\Query\Builder rightJoinSub($query, $as, $first, $operator = null, $second = null)
|
||||
* @method static \Illuminate\Database\Query\Builder crossJoin($table, $first = null, $operator = null, $second = null)
|
||||
* @method static \Illuminate\Database\Query\Builder crossJoinSub($query, $as)
|
||||
* @method static Builder select($columns = [])
|
||||
* @method static Builder selectSub($query, $as)
|
||||
* @method static Builder selectRaw($expression, $bindings = [])
|
||||
* @method static Builder fromSub($query, $as)
|
||||
* @method static Builder fromRaw($expression, $bindings = [])
|
||||
* @method static Builder addSelect($column)
|
||||
* @method static Builder distinct()
|
||||
* @method static Builder from($table, $as = null)
|
||||
* @method static Builder join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false)
|
||||
* @method static Builder joinWhere($table, $first, $operator, $second, $type = 'inner')
|
||||
* @method static Builder joinSub($query, $as, $first, $operator = null, $second = null, $type = 'inner', $where = false)
|
||||
* @method static Builder leftJoin($table, $first, $operator = null, $second = null)
|
||||
* @method static Builder leftJoinWhere($table, $first, $operator, $second)
|
||||
* @method static Builder leftJoinSub($query, $as, $first, $operator = null, $second = null)
|
||||
* @method static Builder rightJoin($table, $first, $operator = null, $second = null)
|
||||
* @method static Builder rightJoinWhere($table, $first, $operator, $second)
|
||||
* @method static Builder rightJoinSub($query, $as, $first, $operator = null, $second = null)
|
||||
* @method static Builder crossJoin($table, $first = null, $operator = null, $second = null)
|
||||
* @method static Builder crossJoinSub($query, $as)
|
||||
* @method static void mergeWheres($wheres, $bindings)
|
||||
* @method static array prepareValueAndOperator($value, $operator, $useDefault = false)
|
||||
* @method static \Illuminate\Database\Query\Builder whereColumn($first, $operator = null, $second = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereColumn($first, $operator = null, $second = null)
|
||||
* @method static \Illuminate\Database\Query\Builder whereRaw($sql, $bindings = [], $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereRaw($sql, $bindings = [])
|
||||
* @method static \Illuminate\Database\Query\Builder whereIn($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereIn($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder whereNotIn($column, $values, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereNotIn($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder whereIntegerInRaw($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereIntegerInRaw($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder whereIntegerNotInRaw($column, $values, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereIntegerNotInRaw($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder whereNull($columns, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereNull($column)
|
||||
* @method static \Illuminate\Database\Query\Builder whereNotNull($columns, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder whereBetween($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder whereBetweenColumns($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereBetween($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereBetweenColumns($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder whereNotBetween($column, $values, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder whereNotBetweenColumns($column, $values, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereNotBetween($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereNotBetweenColumns($column, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereNotNull($column)
|
||||
* @method static \Illuminate\Database\Query\Builder whereDate($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereDate($column, $operator, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder whereTime($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereTime($column, $operator, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder whereDay($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereDay($column, $operator, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder whereMonth($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereMonth($column, $operator, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder whereYear($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereYear($column, $operator, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder whereNested($callback, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder forNestedWhere()
|
||||
* @method static \Illuminate\Database\Query\Builder addNestedWhereQuery($query, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder whereExists($callback, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereExists($callback, $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder whereNotExists($callback, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereNotExists($callback)
|
||||
* @method static \Illuminate\Database\Query\Builder addWhereExistsQuery($query, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder whereRowValues($columns, $operator, $values, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereRowValues($columns, $operator, $values)
|
||||
* @method static \Illuminate\Database\Query\Builder whereJsonContains($column, $value, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereJsonContains($column, $value)
|
||||
* @method static \Illuminate\Database\Query\Builder whereJsonDoesntContain($column, $value, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereJsonDoesntContain($column, $value)
|
||||
* @method static \Illuminate\Database\Query\Builder whereJsonLength($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orWhereJsonLength($column, $operator, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder dynamicWhere($method, $parameters)
|
||||
* @method static \Illuminate\Database\Query\Builder groupBy(...$groups)
|
||||
* @method static \Illuminate\Database\Query\Builder groupByRaw($sql, $bindings = [])
|
||||
* @method static \Illuminate\Database\Query\Builder having($column, $operator = null, $value = null, $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orHaving($column, $operator = null, $value = null)
|
||||
* @method static \Illuminate\Database\Query\Builder havingBetween($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static \Illuminate\Database\Query\Builder havingRaw($sql, $bindings = [], $boolean = 'and')
|
||||
* @method static \Illuminate\Database\Query\Builder orHavingRaw($sql, $bindings = [])
|
||||
* @method static \Illuminate\Database\Query\Builder orderBy($column, $direction = 'asc')
|
||||
* @method static \Illuminate\Database\Query\Builder orderByDesc($column)
|
||||
* @method static \Illuminate\Database\Query\Builder inRandomOrder($seed = '')
|
||||
* @method static \Illuminate\Database\Query\Builder orderByRaw($sql, $bindings = [])
|
||||
* @method static \Illuminate\Database\Query\Builder skip($value)
|
||||
* @method static \Illuminate\Database\Query\Builder offset($value)
|
||||
* @method static \Illuminate\Database\Query\Builder take($value)
|
||||
* @method static \Illuminate\Database\Query\Builder limit($value)
|
||||
* @method static \Illuminate\Database\Query\Builder forPage($page, $perPage = 15)
|
||||
* @method static \Illuminate\Database\Query\Builder forPageBeforeId($perPage = 15, $lastId = 0, $column = 'id')
|
||||
* @method static \Illuminate\Database\Query\Builder forPageAfterId($perPage = 15, $lastId = 0, $column = 'id')
|
||||
* @method static \Illuminate\Database\Query\Builder reorder($column = null, $direction = 'asc')
|
||||
* @method static \Illuminate\Database\Query\Builder union($query, $all = false)
|
||||
* @method static \Illuminate\Database\Query\Builder unionAll($query)
|
||||
* @method static \Illuminate\Database\Query\Builder lock($value = true)
|
||||
* @method static \Illuminate\Database\Query\Builder lockForUpdate()
|
||||
* @method static \Illuminate\Database\Query\Builder sharedLock()
|
||||
* @method static \Illuminate\Database\Query\Builder beforeQuery($callback)
|
||||
* @method static Builder whereColumn($first, $operator = null, $second = null, $boolean = 'and')
|
||||
* @method static Builder orWhereColumn($first, $operator = null, $second = null)
|
||||
* @method static Builder whereRaw($sql, $bindings = [], $boolean = 'and')
|
||||
* @method static Builder orWhereRaw($sql, $bindings = [])
|
||||
* @method static Builder whereIn($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static Builder orWhereIn($column, $values)
|
||||
* @method static Builder whereNotIn($column, $values, $boolean = 'and')
|
||||
* @method static Builder orWhereNotIn($column, $values)
|
||||
* @method static Builder whereIntegerInRaw($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static Builder orWhereIntegerInRaw($column, $values)
|
||||
* @method static Builder whereIntegerNotInRaw($column, $values, $boolean = 'and')
|
||||
* @method static Builder orWhereIntegerNotInRaw($column, $values)
|
||||
* @method static Builder whereNull($columns, $boolean = 'and', $not = false)
|
||||
* @method static Builder orWhereNull($column)
|
||||
* @method static Builder whereNotNull($columns, $boolean = 'and')
|
||||
* @method static Builder whereBetween($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static Builder whereBetweenColumns($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static Builder orWhereBetween($column, $values)
|
||||
* @method static Builder orWhereBetweenColumns($column, $values)
|
||||
* @method static Builder whereNotBetween($column, $values, $boolean = 'and')
|
||||
* @method static Builder whereNotBetweenColumns($column, $values, $boolean = 'and')
|
||||
* @method static Builder orWhereNotBetween($column, $values)
|
||||
* @method static Builder orWhereNotBetweenColumns($column, $values)
|
||||
* @method static Builder orWhereNotNull($column)
|
||||
* @method static Builder whereDate($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static Builder orWhereDate($column, $operator, $value = null)
|
||||
* @method static Builder whereTime($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static Builder orWhereTime($column, $operator, $value = null)
|
||||
* @method static Builder whereDay($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static Builder orWhereDay($column, $operator, $value = null)
|
||||
* @method static Builder whereMonth($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static Builder orWhereMonth($column, $operator, $value = null)
|
||||
* @method static Builder whereYear($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static Builder orWhereYear($column, $operator, $value = null)
|
||||
* @method static Builder whereNested($callback, $boolean = 'and')
|
||||
* @method static Builder forNestedWhere()
|
||||
* @method static Builder addNestedWhereQuery($query, $boolean = 'and')
|
||||
* @method static Builder whereExists($callback, $boolean = 'and', $not = false)
|
||||
* @method static Builder orWhereExists($callback, $not = false)
|
||||
* @method static Builder whereNotExists($callback, $boolean = 'and')
|
||||
* @method static Builder orWhereNotExists($callback)
|
||||
* @method static Builder addWhereExistsQuery($query, $boolean = 'and', $not = false)
|
||||
* @method static Builder whereRowValues($columns, $operator, $values, $boolean = 'and')
|
||||
* @method static Builder orWhereRowValues($columns, $operator, $values)
|
||||
* @method static Builder whereJsonContains($column, $value, $boolean = 'and', $not = false)
|
||||
* @method static Builder orWhereJsonContains($column, $value)
|
||||
* @method static Builder whereJsonDoesntContain($column, $value, $boolean = 'and')
|
||||
* @method static Builder orWhereJsonDoesntContain($column, $value)
|
||||
* @method static Builder whereJsonLength($column, $operator, $value = null, $boolean = 'and')
|
||||
* @method static Builder orWhereJsonLength($column, $operator, $value = null)
|
||||
* @method static Builder dynamicWhere($method, $parameters)
|
||||
* @method static Builder groupBy(...$groups)
|
||||
* @method static Builder groupByRaw($sql, $bindings = [])
|
||||
* @method static Builder having($column, $operator = null, $value = null, $boolean = 'and')
|
||||
* @method static Builder orHaving($column, $operator = null, $value = null)
|
||||
* @method static Builder havingBetween($column, $values, $boolean = 'and', $not = false)
|
||||
* @method static Builder havingRaw($sql, $bindings = [], $boolean = 'and')
|
||||
* @method static Builder orHavingRaw($sql, $bindings = [])
|
||||
* @method static Builder orderBy($column, $direction = 'asc')
|
||||
* @method static Builder orderByDesc($column)
|
||||
* @method static Builder inRandomOrder($seed = '')
|
||||
* @method static Builder orderByRaw($sql, $bindings = [])
|
||||
* @method static Builder skip($value)
|
||||
* @method static Builder offset($value)
|
||||
* @method static Builder take($value)
|
||||
* @method static Builder limit($value)
|
||||
* @method static Builder forPage($page, $perPage = 15)
|
||||
* @method static Builder forPageBeforeId($perPage = 15, $lastId = 0, $column = 'id')
|
||||
* @method static Builder forPageAfterId($perPage = 15, $lastId = 0, $column = 'id')
|
||||
* @method static Builder reorder($column = null, $direction = 'asc')
|
||||
* @method static Builder union($query, $all = false)
|
||||
* @method static Builder unionAll($query)
|
||||
* @method static Builder lock($value = true)
|
||||
* @method static Builder lockForUpdate()
|
||||
* @method static Builder sharedLock()
|
||||
* @method static Builder beforeQuery($callback)
|
||||
* @method static void applyBeforeQueryCallbacks()
|
||||
* @method static string toSql()
|
||||
* @method static int getCountForPagination($columns = [])
|
||||
@@ -228,19 +238,19 @@ use Illuminate\Database\Eloquent\Model as BaseModel;
|
||||
* @method static int insertUsing($columns, $query)
|
||||
* @method static bool updateOrInsert($attributes, $values = [])
|
||||
* @method static void truncate()
|
||||
* @method static \Illuminate\Database\Query\Expression raw($value)
|
||||
* @method static Expression raw($value)
|
||||
* @method static array getBindings()
|
||||
* @method static array getRawBindings()
|
||||
* @method static \Illuminate\Database\Query\Builder setBindings($bindings, $type = 'where')
|
||||
* @method static \Illuminate\Database\Query\Builder addBinding($value, $type = 'where')
|
||||
* @method static \Illuminate\Database\Query\Builder mergeBindings($query)
|
||||
* @method static Builder setBindings($bindings, $type = 'where')
|
||||
* @method static Builder addBinding($value, $type = 'where')
|
||||
* @method static Builder mergeBindings($query)
|
||||
* @method static array cleanBindings($bindings)
|
||||
* @method static \Illuminate\Database\Query\Processors\Processor getProcessor()
|
||||
* @method static \Illuminate\Database\Query\Grammars\Grammar getGrammar()
|
||||
* @method static \Illuminate\Database\Query\Builder useWritePdo()
|
||||
* @method static Processor getProcessor()
|
||||
* @method static Grammar getGrammar()
|
||||
* @method static Builder useWritePdo()
|
||||
* @method static static cloneWithout($properties)
|
||||
* @method static static cloneWithoutBindings($except)
|
||||
* @method static \Illuminate\Database\Query\Builder dump()
|
||||
* @method static Builder dump()
|
||||
* @method static void dd()
|
||||
* @method static void macro($name, $macro)
|
||||
* @method static void mixin($mixin, $replace = true)
|
||||
@@ -249,4 +259,4 @@ use Illuminate\Database\Eloquent\Model as BaseModel;
|
||||
class Model extends BaseModel
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,30 +2,37 @@
|
||||
|
||||
namespace support;
|
||||
|
||||
use function defined;
|
||||
use function is_callable;
|
||||
use function is_file;
|
||||
use function method_exists;
|
||||
|
||||
class Plugin
|
||||
{
|
||||
/**
|
||||
* Install.
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public static function install($event)
|
||||
{
|
||||
static::findHepler();
|
||||
static::findHelper();
|
||||
$operation = $event->getOperation();
|
||||
$autoload = \method_exists($operation, 'getPackage') ? $operation->getPackage()->getAutoload() : $operation->getTargetPackage()->getAutoload();
|
||||
$autoload = method_exists($operation, 'getPackage') ? $operation->getPackage()->getAutoload() : $operation->getTargetPackage()->getAutoload();
|
||||
if (!isset($autoload['psr-4'])) {
|
||||
return;
|
||||
}
|
||||
foreach ($autoload['psr-4'] as $namespace => $path) {
|
||||
$install_function = "\\{$namespace}Install::install";
|
||||
$plugin_const = "\\{$namespace}Install::WEBMAN_PLUGIN";
|
||||
if (\defined($plugin_const) && \is_callable($install_function)) {
|
||||
$install_function();
|
||||
$installFunction = "\\{$namespace}Install::install";
|
||||
$pluginConst = "\\{$namespace}Install::WEBMAN_PLUGIN";
|
||||
if (defined($pluginConst) && is_callable($installFunction)) {
|
||||
$installFunction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update.
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
@@ -35,33 +42,35 @@ class Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall.
|
||||
* @param $event
|
||||
* @return void
|
||||
*/
|
||||
public static function uninstall($event)
|
||||
{
|
||||
static::findHepler();
|
||||
static::findHelper();
|
||||
$autoload = $event->getOperation()->getPackage()->getAutoload();
|
||||
if (!isset($autoload['psr-4'])) {
|
||||
return;
|
||||
}
|
||||
foreach ($autoload['psr-4'] as $namespace => $path) {
|
||||
$uninstall_function = "\\{$namespace}Install::uninstall";
|
||||
$plugin_const = "\\{$namespace}Install::WEBMAN_PLUGIN";
|
||||
if (defined($plugin_const) && is_callable($uninstall_function)) {
|
||||
$uninstall_function();
|
||||
$uninstallFunction = "\\{$namespace}Install::uninstall";
|
||||
$pluginConst = "\\{$namespace}Install::WEBMAN_PLUGIN";
|
||||
if (defined($pluginConst) && is_callable($uninstallFunction)) {
|
||||
$uninstallFunction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FindHelper.
|
||||
* @return void
|
||||
*/
|
||||
protected static function findHepler()
|
||||
protected static function findHelper()
|
||||
{
|
||||
// Plugin.php in vendor
|
||||
$file = __DIR__ . '/../../../../../support/helpers.php';
|
||||
if (\is_file($file)) {
|
||||
if (is_file($file)) {
|
||||
require_once $file;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
namespace support;
|
||||
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Redis\Events\CommandExecuted;
|
||||
use Illuminate\Redis\Connections\Connection;
|
||||
use Illuminate\Redis\RedisManager;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
use function class_exists;
|
||||
use function config;
|
||||
use function in_array;
|
||||
|
||||
|
||||
/**
|
||||
@@ -184,7 +187,7 @@ use Workerman\Worker;
|
||||
* @method static mixed watch($keys)
|
||||
* @method static mixed unwatch($keys)
|
||||
* Scripting methods
|
||||
* @method mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method static mixed eval($script, $numkeys, $keyOrArg1 = null, $keyOrArgN = null)
|
||||
* @method static mixed evalSha($scriptSha, $numkeys, ...$arguments)
|
||||
* @method static mixed script($command, ...$scripts)
|
||||
* @method static mixed client(...$args)
|
||||
@@ -209,7 +212,7 @@ class Redis
|
||||
/**
|
||||
* @var RedisManager
|
||||
*/
|
||||
protected static $_instance = null;
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* need to install phpredis extension
|
||||
@@ -225,7 +228,7 @@ class Redis
|
||||
/**
|
||||
* Support client collection
|
||||
*/
|
||||
static $_allowClient = [
|
||||
static $allowClient = [
|
||||
self::PHPREDIS_CLIENT,
|
||||
self::PREDIS_CLIENT
|
||||
];
|
||||
@@ -233,26 +236,27 @@ class Redis
|
||||
/**
|
||||
* @return RedisManager
|
||||
*/
|
||||
public static function instance()
|
||||
public static function instance(): ?RedisManager
|
||||
{
|
||||
if (!static::$_instance) {
|
||||
$config = \config('redis');
|
||||
if (!static::$instance) {
|
||||
$config = config('redis');
|
||||
$client = $config['client'] ?? self::PHPREDIS_CLIENT;
|
||||
|
||||
if (!\in_array($client, static::$_allowClient)) {
|
||||
if (!in_array($client, static::$allowClient)) {
|
||||
$client = self::PHPREDIS_CLIENT;
|
||||
}
|
||||
|
||||
static::$_instance = new RedisManager('', $client, $config);
|
||||
static::$instance = new RedisManager('', $client, $config);
|
||||
}
|
||||
return static::$_instance;
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connection.
|
||||
* @param string $name
|
||||
* @return \Illuminate\Redis\Connections\Connection
|
||||
* @return Connection
|
||||
*/
|
||||
public static function connection(string $name = 'default')
|
||||
public static function connection(string $name = 'default'): Connection
|
||||
{
|
||||
static $timers = [];
|
||||
$connection = static::instance()->connection($name);
|
||||
@@ -260,7 +264,7 @@ class Redis
|
||||
$timers[$name] = Worker::getAllWorkers() ? Timer::add(55, function () use ($connection) {
|
||||
$connection->get('ping');
|
||||
}) : 1;
|
||||
if (\class_exists(Dispatcher::class)) {
|
||||
if (class_exists(Dispatcher::class)) {
|
||||
$connection->setEventDispatcher(new Dispatcher());
|
||||
}
|
||||
}
|
||||
@@ -274,6 +278,6 @@ class Redis
|
||||
*/
|
||||
public static function __callStatic(string $name, array $arguments)
|
||||
{
|
||||
return static::connection('default')->{$name}(... $arguments);
|
||||
return static::connection()->{$name}(... $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,13 @@ namespace support;
|
||||
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Webman\Exception\NotFoundException;
|
||||
use function basename;
|
||||
use function config;
|
||||
use function get_realpath;
|
||||
use function glob;
|
||||
use function pathinfo;
|
||||
use function request;
|
||||
use function substr;
|
||||
|
||||
/**
|
||||
* Class Translation
|
||||
@@ -30,22 +37,24 @@ class Translation
|
||||
/**
|
||||
* @var Translator[]
|
||||
*/
|
||||
protected static $_instance = [];
|
||||
protected static $instance = [];
|
||||
|
||||
/**
|
||||
* Instance.
|
||||
* @param string $plugin
|
||||
* @return Translator
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public static function instance(string $plugin = '')
|
||||
public static function instance(string $plugin = ''): Translator
|
||||
{
|
||||
if (!isset(static::$_instance[$plugin])) {
|
||||
$config = \config($plugin ? "plugin.$plugin.translation" : 'translation', []);
|
||||
if (!isset(static::$instance[$plugin])) {
|
||||
$config = config($plugin ? "plugin.$plugin.translation" : 'translation', []);
|
||||
// Phar support. Compatible with the 'realpath' function in the phar file.
|
||||
if (!$translations_path = \get_realpath($config['path'])) {
|
||||
if (!$translationsPath = get_realpath($config['path'])) {
|
||||
throw new NotFoundException("File {$config['path']} not found");
|
||||
}
|
||||
|
||||
static::$_instance[$plugin] = $translator = new Translator($config['locale']);
|
||||
static::$instance[$plugin] = $translator = new Translator($config['locale']);
|
||||
$translator->setFallbackLocales($config['fallback_locale']);
|
||||
|
||||
$classes = [
|
||||
@@ -61,17 +70,17 @@ class Translation
|
||||
|
||||
foreach ($classes as $class => $opts) {
|
||||
$translator->addLoader($opts['format'], new $class);
|
||||
foreach (\glob($translations_path . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . '*' . $opts['extension']) as $file) {
|
||||
$domain = \basename($file, $opts['extension']);
|
||||
$dir_name = \pathinfo($file, PATHINFO_DIRNAME);
|
||||
$locale = \substr(strrchr($dir_name, DIRECTORY_SEPARATOR), 1);
|
||||
foreach (glob($translationsPath . DIRECTORY_SEPARATOR . '*' . DIRECTORY_SEPARATOR . '*' . $opts['extension']) as $file) {
|
||||
$domain = basename($file, $opts['extension']);
|
||||
$dirName = pathinfo($file, PATHINFO_DIRNAME);
|
||||
$locale = substr(strrchr($dirName, DIRECTORY_SEPARATOR), 1);
|
||||
if ($domain && $locale) {
|
||||
$translator->addResource($opts['format'], $file, $locale, $domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return static::$_instance[$plugin];
|
||||
return static::$instance[$plugin];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +91,7 @@ class Translation
|
||||
*/
|
||||
public static function __callStatic(string $name, array $arguments)
|
||||
{
|
||||
$request = \request();
|
||||
$request = request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
return static::instance($plugin)->{$name}(... $arguments);
|
||||
}
|
||||
|
||||
@@ -14,18 +14,22 @@
|
||||
|
||||
namespace support;
|
||||
|
||||
use function config;
|
||||
use function request;
|
||||
|
||||
class View
|
||||
{
|
||||
/**
|
||||
* Assign.
|
||||
* @param mixed $name
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
public static function assign($name, $value = null)
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
|
||||
$request = request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$handler = config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
|
||||
$handler::assign($name, $value);
|
||||
}
|
||||
}
|
||||
@@ -14,17 +14,19 @@
|
||||
|
||||
namespace support\bootstrap;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Container\Container as IlluminateContainer;
|
||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\MySqlConnection;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Jenssegers\Mongodb\Connection as MongodbConnection;
|
||||
use support\Db;
|
||||
use support\Container;
|
||||
use Throwable;
|
||||
use Webman\Bootstrap;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
use function class_exists;
|
||||
use function config;
|
||||
|
||||
/**
|
||||
* Class Laravel
|
||||
@@ -33,23 +35,23 @@ use Workerman\Worker;
|
||||
class LaravelDb implements Bootstrap
|
||||
{
|
||||
/**
|
||||
* @param Worker $worker
|
||||
* @param Worker|null $worker
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function start($worker)
|
||||
public static function start(?Worker $worker)
|
||||
{
|
||||
if (!class_exists(Capsule::class)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = \config('database', []);
|
||||
$config = config('database', []);
|
||||
$connections = $config['connections'] ?? [];
|
||||
if (!$connections) {
|
||||
return;
|
||||
}
|
||||
|
||||
$capsule = new Capsule;
|
||||
$capsule = new Capsule(IlluminateContainer::getInstance());
|
||||
|
||||
$capsule->getDatabaseManager()->extend('mongodb', function ($config, $name) {
|
||||
$config['name'] = $name;
|
||||
@@ -58,16 +60,16 @@ class LaravelDb implements Bootstrap
|
||||
|
||||
$default = $config['default'] ?? false;
|
||||
if ($default) {
|
||||
$default_config = $connections[$config['default']];
|
||||
$capsule->addConnection($default_config);
|
||||
$defaultConfig = $connections[$config['default']];
|
||||
$capsule->addConnection($defaultConfig);
|
||||
}
|
||||
|
||||
foreach ($connections as $name => $config) {
|
||||
$capsule->addConnection($config, $name);
|
||||
}
|
||||
|
||||
if (\class_exists(Dispatcher::class)) {
|
||||
$capsule->setEventDispatcher(new Dispatcher(new Container));
|
||||
if (class_exists(Dispatcher::class) && !$capsule->getEventDispatcher()) {
|
||||
$capsule->setEventDispatcher(Container::make(Dispatcher::class, [IlluminateContainer::getInstance()]));
|
||||
}
|
||||
|
||||
$capsule->setAsGlobal();
|
||||
@@ -76,20 +78,13 @@ class LaravelDb implements Bootstrap
|
||||
|
||||
// Heartbeat
|
||||
if ($worker) {
|
||||
Timer::add(55, function () use ($default, $connections) {
|
||||
if (!class_exists(Connection::class, false)) {
|
||||
return;
|
||||
}
|
||||
foreach ($connections as $key => $item) {
|
||||
if ($item['driver'] == 'mysql') {
|
||||
Timer::add(55, function () use ($default, $connections, $capsule) {
|
||||
foreach ($capsule->getDatabaseManager()->getConnections() as $connection) {
|
||||
/* @var MySqlConnection $connection **/
|
||||
if ($connection->getConfig('driver') == 'mysql') {
|
||||
try {
|
||||
if ($key == $default) {
|
||||
Db::select('select 1');
|
||||
} else {
|
||||
Db::connection($key)->select('select 1');
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
}
|
||||
$connection->select('select 1');
|
||||
} catch (Throwable $e) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -97,14 +92,22 @@ class LaravelDb implements Bootstrap
|
||||
|
||||
// Paginator
|
||||
if (class_exists(Paginator::class)) {
|
||||
Paginator::queryStringResolver(function () {
|
||||
return request()->queryString();
|
||||
});
|
||||
if (method_exists(Paginator::class, 'queryStringResolver')) {
|
||||
Paginator::queryStringResolver(function () {
|
||||
$request = request();
|
||||
return $request ? $request->queryString() : null;
|
||||
});
|
||||
}
|
||||
Paginator::currentPathResolver(function () {
|
||||
return request()->path();
|
||||
$request = request();
|
||||
return $request ? $request->path(): '/';
|
||||
});
|
||||
Paginator::currentPageResolver(function ($page_name = 'page') {
|
||||
$page = (int)request()->input($page_name, 1);
|
||||
Paginator::currentPageResolver(function ($pageName = 'page') {
|
||||
$request = request();
|
||||
if (!$request) {
|
||||
return 1;
|
||||
}
|
||||
$page = (int)($request->input($pageName, 1));
|
||||
return $page > 0 ? $page : 1;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ use Webman\Bootstrap;
|
||||
use Workerman\Protocols\Http;
|
||||
use Workerman\Protocols\Http\Session as SessionBase;
|
||||
use Workerman\Worker;
|
||||
use function config;
|
||||
use function property_exists;
|
||||
|
||||
/**
|
||||
* Class Session
|
||||
@@ -27,13 +29,13 @@ class Session implements Bootstrap
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Worker $worker
|
||||
* @param Worker|null $worker
|
||||
* @return void
|
||||
*/
|
||||
public static function start($worker)
|
||||
public static function start(?Worker $worker)
|
||||
{
|
||||
$config = \config('session');
|
||||
if (\property_exists(SessionBase::class, 'name')) {
|
||||
$config = config('session');
|
||||
if (property_exists(SessionBase::class, 'name')) {
|
||||
SessionBase::$name = $config['session_name'];
|
||||
} else {
|
||||
Http::sessionName($config['session_name']);
|
||||
@@ -51,7 +53,7 @@ class Session implements Bootstrap
|
||||
'secure' => 'secure',
|
||||
];
|
||||
foreach ($map as $key => $name) {
|
||||
if (isset($config[$key]) && \property_exists(SessionBase::class, $name)) {
|
||||
if (isset($config[$key]) && property_exists(SessionBase::class, $name)) {
|
||||
SessionBase::${$name} = $config[$key];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
namespace support\exception;
|
||||
|
||||
use Exception;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use function json_encode;
|
||||
|
||||
/**
|
||||
* Class BusinessException
|
||||
@@ -28,9 +29,9 @@ class BusinessException extends Exception
|
||||
{
|
||||
if ($request->expectsJson()) {
|
||||
$code = $this->getCode();
|
||||
$json = ['code' => $code ? $code : 500, 'msg' => $this->getMessage()];
|
||||
$json = ['code' => $code ?: 500, 'msg' => $this->getMessage()];
|
||||
return new Response(200, ['Content-Type' => 'application/json'],
|
||||
\json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
return new Response(200, [], $this->getMessage());
|
||||
}
|
||||
|
||||
@@ -16,6 +16,13 @@ namespace support\view;
|
||||
|
||||
use Jenssegers\Blade\Blade as BladeView;
|
||||
use Webman\View;
|
||||
use function app_path;
|
||||
use function array_merge;
|
||||
use function base_path;
|
||||
use function config;
|
||||
use function is_array;
|
||||
use function request;
|
||||
use function runtime_path;
|
||||
|
||||
/**
|
||||
* Class Blade
|
||||
@@ -27,37 +34,46 @@ class Blade implements View
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_vars = [];
|
||||
protected static $vars = [];
|
||||
|
||||
/**
|
||||
* Assign.
|
||||
* @param string|array $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function assign($name, $value = null)
|
||||
{
|
||||
static::$_vars = \array_merge(static::$_vars, \is_array($name) ? $name : [$name => $value]);
|
||||
static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return string
|
||||
*/
|
||||
public static function render(string $template, array $vars, string $app = null)
|
||||
public static function render(string $template, array $vars, string $app = null, string $plugin = null): string
|
||||
{
|
||||
static $views = [];
|
||||
$request = \request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$request = request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$app = $app === null ? $request->app : $app;
|
||||
$base_view_path = $plugin ? \base_path() . "/plugin/$plugin/app" : \app_path();
|
||||
if (!isset($views[$app])) {
|
||||
$view_path = $app === '' ? "$base_view_path/view" : "$base_view_path/$app/view";
|
||||
$views[$app] = new BladeView($view_path, \runtime_path() . '/views');
|
||||
$configPrefix = $plugin ? "plugin.$plugin." : '';
|
||||
$baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path();
|
||||
$key = "$plugin-$app";
|
||||
if (!isset($views[$key])) {
|
||||
$viewPath = $app === '' ? "$baseViewPath/view" : "$baseViewPath/$app/view";
|
||||
$views[$key] = new BladeView($viewPath, runtime_path() . '/views');
|
||||
$extension = config("{$configPrefix}view.extension");
|
||||
if ($extension) {
|
||||
$extension($views[$key]);
|
||||
}
|
||||
}
|
||||
$vars = \array_merge(static::$_vars, $vars);
|
||||
$content = $views[$app]->render($template, $vars);
|
||||
static::$_vars = [];
|
||||
$vars = array_merge(static::$vars, $vars);
|
||||
$content = $views[$key]->render($template, $vars);
|
||||
static::$vars = [];
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,18 @@
|
||||
|
||||
namespace support\view;
|
||||
|
||||
use Webman\View;
|
||||
use Throwable;
|
||||
use Webman\View;
|
||||
use function app_path;
|
||||
use function array_merge;
|
||||
use function base_path;
|
||||
use function config;
|
||||
use function extract;
|
||||
use function is_array;
|
||||
use function ob_end_clean;
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
use function request;
|
||||
|
||||
/**
|
||||
* Class Raw
|
||||
@@ -26,46 +36,49 @@ class Raw implements View
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_vars = [];
|
||||
protected static $vars = [];
|
||||
|
||||
/**
|
||||
* Assign.
|
||||
* @param string|array $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function assign($name, $value = null)
|
||||
{
|
||||
static::$_vars = \array_merge(static::$_vars, \is_array($name) ? $name : [$name => $value]);
|
||||
static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return false|string
|
||||
*/
|
||||
public static function render(string $template, array $vars, string $app = null)
|
||||
public static function render(string $template, array $vars, string $app = null, string $plugin = null): string
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$config_prefix = $plugin ? "plugin.$plugin." : '';
|
||||
$view_suffix = \config("{$config_prefix}view.options.view_suffix", 'html');
|
||||
$request = request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$configPrefix = $plugin ? "plugin.$plugin." : '';
|
||||
$viewSuffix = config("{$configPrefix}view.options.view_suffix", 'html');
|
||||
$app = $app === null ? $request->app : $app;
|
||||
$base_view_path = $plugin ? \base_path() . "/plugin/$plugin/app" : \app_path();
|
||||
$__template_path__ = $app === '' ? "$base_view_path/view/$template.$view_suffix" : "$base_view_path/$app/view/$template.$view_suffix";
|
||||
$baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path();
|
||||
$__template_path__ = $app === '' ? "$baseViewPath/view/$template.$viewSuffix" : "$baseViewPath/$app/view/$template.$viewSuffix";
|
||||
|
||||
\extract(static::$_vars);
|
||||
\extract($vars);
|
||||
\ob_start();
|
||||
extract(static::$vars);
|
||||
extract($vars);
|
||||
ob_start();
|
||||
// Try to include php file.
|
||||
try {
|
||||
include $__template_path__;
|
||||
} catch (Throwable $e) {
|
||||
static::$_vars = [];
|
||||
\ob_end_clean();
|
||||
static::$vars = [];
|
||||
ob_end_clean();
|
||||
throw $e;
|
||||
}
|
||||
static::$_vars = [];
|
||||
return \ob_get_clean();
|
||||
static::$vars = [];
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,15 @@ namespace support\view;
|
||||
|
||||
use think\Template;
|
||||
use Webman\View;
|
||||
use function app_path;
|
||||
use function array_merge;
|
||||
use function base_path;
|
||||
use function config;
|
||||
use function is_array;
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
use function request;
|
||||
use function runtime_path;
|
||||
|
||||
/**
|
||||
* Class Blade
|
||||
@@ -26,44 +35,47 @@ class ThinkPHP implements View
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_vars = [];
|
||||
protected static $vars = [];
|
||||
|
||||
/**
|
||||
* Assign.
|
||||
* @param string|array $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function assign($name, $value = null)
|
||||
{
|
||||
static::$_vars = \array_merge(static::$_vars, \is_array($name) ? $name : [$name => $value]);
|
||||
static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return false|string
|
||||
*/
|
||||
public static function render(string $template, array $vars, string $app = null)
|
||||
public static function render(string $template, array $vars, string $app = null, string $plugin = null): string
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$request = request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$app = $app === null ? $request->app : $app;
|
||||
$config_prefix = $plugin ? "plugin.$plugin." : '';
|
||||
$view_suffix = \config("{$config_prefix}view.options.view_suffix", 'html');
|
||||
$base_view_path = $plugin ? \base_path() . "/plugin/$plugin/app" : \app_path();
|
||||
$view_path = $app === '' ? "$base_view_path/view/" : "$base_view_path/$app/view/";
|
||||
$default_options = [
|
||||
'view_path' => $view_path,
|
||||
'cache_path' => \runtime_path() . '/views/',
|
||||
'view_suffix' => $view_suffix
|
||||
$configPrefix = $plugin ? "plugin.$plugin." : '';
|
||||
$viewSuffix = config("{$configPrefix}view.options.view_suffix", 'html');
|
||||
$baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path();
|
||||
$viewPath = $app === '' ? "$baseViewPath/view/" : "$baseViewPath/$app/view/";
|
||||
$defaultOptions = [
|
||||
'view_path' => $viewPath,
|
||||
'cache_path' => runtime_path() . '/views/',
|
||||
'view_suffix' => $viewSuffix
|
||||
];
|
||||
$options = $default_options + \config("{$config_prefix}view.options", []);
|
||||
$options = $defaultOptions + config("{$configPrefix}view.options", []);
|
||||
$views = new Template($options);
|
||||
\ob_start();
|
||||
$vars = \array_merge(static::$_vars, $vars);
|
||||
ob_start();
|
||||
$vars = array_merge(static::$vars, $vars);
|
||||
$views->fetch($template, $vars);
|
||||
$content = \ob_get_clean();
|
||||
static::$_vars = [];
|
||||
$content = ob_get_clean();
|
||||
static::$vars = [];
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,17 @@
|
||||
namespace support\view;
|
||||
|
||||
use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Webman\View;
|
||||
use function app_path;
|
||||
use function array_merge;
|
||||
use function base_path;
|
||||
use function config;
|
||||
use function is_array;
|
||||
use function request;
|
||||
|
||||
/**
|
||||
* Class Blade
|
||||
@@ -27,40 +36,47 @@ class Twig implements View
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $_vars = [];
|
||||
protected static $vars = [];
|
||||
|
||||
/**
|
||||
* Assign.
|
||||
* @param string|array $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public static function assign($name, $value = null)
|
||||
{
|
||||
static::$_vars = \array_merge(static::$_vars, \is_array($name) ? $name : [$name => $value]);
|
||||
static::$vars = array_merge(static::$vars, is_array($name) ? $name : [$name => $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render.
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return string
|
||||
*/
|
||||
public static function render(string $template, array $vars, string $app = null)
|
||||
public static function render(string $template, array $vars, string $app = null, string $plugin = null): string
|
||||
{
|
||||
static $views = [];
|
||||
$request = \request();
|
||||
$plugin = $request->plugin ?? '';
|
||||
$request = request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$app = $app === null ? $request->app : $app;
|
||||
$config_prefix = $plugin ? "plugin.$plugin." : '';
|
||||
$view_suffix = \config("{$config_prefix}view.options.view_suffix", 'html');
|
||||
$key = "{$plugin}-{$request->app}";
|
||||
$configPrefix = $plugin ? "plugin.$plugin." : '';
|
||||
$viewSuffix = config("{$configPrefix}view.options.view_suffix", 'html');
|
||||
$key = "$plugin-$app";
|
||||
if (!isset($views[$key])) {
|
||||
$base_view_path = $plugin ? \base_path() . "/plugin/$plugin/app" : \app_path();
|
||||
$view_path = $app === '' ? "$base_view_path/view/" : "$base_view_path/$app/view/";
|
||||
$views[$key] = new Environment(new FilesystemLoader($view_path), \config("{$config_prefix}view.options", []));
|
||||
$baseViewPath = $plugin ? base_path() . "/plugin/$plugin/app" : app_path();
|
||||
$viewPath = $app === '' ? "$baseViewPath/view/" : "$baseViewPath/$app/view/";
|
||||
$views[$key] = new Environment(new FilesystemLoader($viewPath), config("{$configPrefix}view.options", []));
|
||||
$extension = config("{$configPrefix}view.extension");
|
||||
if ($extension) {
|
||||
$extension($views[$key]);
|
||||
}
|
||||
}
|
||||
$vars = \array_merge(static::$_vars, $vars);
|
||||
$content = $views[$key]->render("$template.$view_suffix", $vars);
|
||||
static::$_vars = [];
|
||||
$vars = array_merge(static::$vars, $vars);
|
||||
$content = $views[$key]->render("$template.$viewSuffix", $vars);
|
||||
static::$vars = [];
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,11 @@
|
||||
*/
|
||||
namespace Workerman\Connection;
|
||||
|
||||
use StdClass;
|
||||
use Workerman\Events\EventInterface;
|
||||
use Workerman\Lib\Timer;
|
||||
use Workerman\Worker;
|
||||
use \Exception;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* AsyncTcpConnection.
|
||||
@@ -164,6 +165,7 @@ class AsyncTcpConnection extends TcpConnection
|
||||
$this->maxSendBufferSize = self::$defaultMaxSendBufferSize;
|
||||
$this->maxPackageSize = self::$defaultMaxPackageSize;
|
||||
$this->_contextOption = $context_option;
|
||||
$this->context = new StdClass;
|
||||
static::$connections[$this->_id] = $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -157,6 +157,13 @@ class TcpConnection extends ConnectionInterface
|
||||
*/
|
||||
public $maxSendBufferSize = 1048576;
|
||||
|
||||
/**
|
||||
* Context.
|
||||
*
|
||||
* @var object|null
|
||||
*/
|
||||
public $context = null;
|
||||
|
||||
/**
|
||||
* Default send buffer size.
|
||||
*
|
||||
@@ -170,7 +177,7 @@ class TcpConnection extends ConnectionInterface
|
||||
* @var int
|
||||
*/
|
||||
public $maxPackageSize = 1048576;
|
||||
|
||||
|
||||
/**
|
||||
* Default maximum acceptable packet size.
|
||||
*
|
||||
@@ -285,6 +292,7 @@ class TcpConnection extends ConnectionInterface
|
||||
$this->maxPackageSize = self::$defaultMaxPackageSize;
|
||||
$this->_remoteAddress = $remote_address;
|
||||
static::$connections[$this->id] = $this;
|
||||
$this->context = new \stdClass;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -720,23 +728,23 @@ class TcpConnection extends ConnectionInterface
|
||||
return false;
|
||||
}
|
||||
$async = $this instanceof AsyncTcpConnection;
|
||||
|
||||
|
||||
/**
|
||||
* We disabled ssl3 because https://blog.qualys.com/ssllabs/2014/10/15/ssl-3-is-dead-killed-by-the-poodle-attack.
|
||||
* You can enable ssl3 by the codes below.
|
||||
*/
|
||||
* We disabled ssl3 because https://blog.qualys.com/ssllabs/2014/10/15/ssl-3-is-dead-killed-by-the-poodle-attack.
|
||||
* You can enable ssl3 by the codes below.
|
||||
*/
|
||||
/*if($async){
|
||||
$type = STREAM_CRYPTO_METHOD_SSLv2_CLIENT | STREAM_CRYPTO_METHOD_SSLv23_CLIENT | STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
|
||||
}else{
|
||||
$type = STREAM_CRYPTO_METHOD_SSLv2_SERVER | STREAM_CRYPTO_METHOD_SSLv23_SERVER | STREAM_CRYPTO_METHOD_SSLv3_SERVER;
|
||||
}*/
|
||||
|
||||
|
||||
if($async){
|
||||
$type = \STREAM_CRYPTO_METHOD_SSLv2_CLIENT | \STREAM_CRYPTO_METHOD_SSLv23_CLIENT;
|
||||
}else{
|
||||
$type = \STREAM_CRYPTO_METHOD_SSLv2_SERVER | \STREAM_CRYPTO_METHOD_SSLv23_SERVER;
|
||||
}
|
||||
|
||||
|
||||
// Hidden error.
|
||||
\set_error_handler(function($errno, $errstr, $file){
|
||||
if (!Worker::$daemonize) {
|
||||
@@ -822,7 +830,7 @@ class TcpConnection extends ConnectionInterface
|
||||
}
|
||||
|
||||
$this->_status = self::STATUS_CLOSING;
|
||||
|
||||
|
||||
if ($this->_sendBuffer === '') {
|
||||
$this->destroy();
|
||||
} else {
|
||||
@@ -882,7 +890,7 @@ class TcpConnection extends ConnectionInterface
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether send buffer is Empty.
|
||||
*
|
||||
@@ -890,7 +898,7 @@ class TcpConnection extends ConnectionInterface
|
||||
*/
|
||||
public function bufferIsEmpty()
|
||||
{
|
||||
return empty($this->_sendBuffer);
|
||||
return empty($this->_sendBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -546,26 +546,27 @@ class Request
|
||||
if (\preg_match('/name="(.*?)"; filename="(.*?)"/i', $value, $match)) {
|
||||
$error = 0;
|
||||
$tmp_file = '';
|
||||
$file_name = $match[2];
|
||||
$size = \strlen($boundary_value);
|
||||
$tmp_upload_dir = HTTP::uploadTmpDir();
|
||||
if (!$tmp_upload_dir) {
|
||||
$error = UPLOAD_ERR_NO_TMP_DIR;
|
||||
} else if ($boundary_value === '') {
|
||||
} else if ($boundary_value === '' && $file_name === '') {
|
||||
$error = UPLOAD_ERR_NO_FILE;
|
||||
} else {
|
||||
$tmp_file = \tempnam($tmp_upload_dir, 'workerman.upload.');
|
||||
if ($tmp_file === false || false == \file_put_contents($tmp_file, $boundary_value)) {
|
||||
if ($tmp_file === false || false === \file_put_contents($tmp_file, $boundary_value)) {
|
||||
$error = UPLOAD_ERR_CANT_WRITE;
|
||||
}
|
||||
}
|
||||
$upload_key = $match[1];
|
||||
// Parse upload files.
|
||||
$file = [
|
||||
'name' => $match[2],
|
||||
'name' => $file_name,
|
||||
'tmp_name' => $tmp_file,
|
||||
'size' => $size,
|
||||
'error' => $error,
|
||||
'type' => null,
|
||||
'type' => '',
|
||||
];
|
||||
break;
|
||||
} // Is post field.
|
||||
|
||||
315
vendor/workerman/workerman/Protocols/Websocket.php
vendored
315
vendor/workerman/workerman/Protocols/Websocket.php
vendored
@@ -11,10 +11,12 @@
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Workerman\Protocols;
|
||||
|
||||
use Workerman\Connection\ConnectionInterface;
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use Workerman\Protocols\Http\Request;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
@@ -29,6 +31,13 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
*/
|
||||
const BINARY_TYPE_BLOB = "\x81";
|
||||
|
||||
/**
|
||||
* Websocket blob type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const BINARY_TYPE_BLOB_DEFLATE = "\xc1";
|
||||
|
||||
/**
|
||||
* Websocket arraybuffer type.
|
||||
*
|
||||
@@ -36,10 +45,17 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
*/
|
||||
const BINARY_TYPE_ARRAYBUFFER = "\x82";
|
||||
|
||||
/**
|
||||
* Websocket arraybuffer type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const BINARY_TYPE_ARRAYBUFFER_DEFLATE = "\xc2";
|
||||
|
||||
/**
|
||||
* Check the integrity of the package.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param ConnectionInterface $connection
|
||||
* @return int
|
||||
*/
|
||||
@@ -53,23 +69,23 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
}
|
||||
|
||||
// Has not yet completed the handshake.
|
||||
if (empty($connection->websocketHandshake)) {
|
||||
if (empty($connection->context->websocketHandshake)) {
|
||||
return static::dealHandshake($buffer, $connection);
|
||||
}
|
||||
|
||||
// Buffer websocket frame data.
|
||||
if ($connection->websocketCurrentFrameLength) {
|
||||
if ($connection->context->websocketCurrentFrameLength) {
|
||||
// We need more frame data.
|
||||
if ($connection->websocketCurrentFrameLength > $recv_len) {
|
||||
if ($connection->context->websocketCurrentFrameLength > $recv_len) {
|
||||
// Return 0, because it is not clear the full packet length, waiting for the frame of fin=1.
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
$firstbyte = \ord($buffer[0]);
|
||||
$secondbyte = \ord($buffer[1]);
|
||||
$data_len = $secondbyte & 127;
|
||||
$is_fin_frame = $firstbyte >> 7;
|
||||
$masked = $secondbyte >> 7;
|
||||
$first_byte = \ord($buffer[0]);
|
||||
$second_byte = \ord($buffer[1]);
|
||||
$data_len = $second_byte & 127;
|
||||
$is_fin_frame = $first_byte >> 7;
|
||||
$masked = $second_byte >> 7;
|
||||
|
||||
if (!$masked) {
|
||||
Worker::safeEcho("frame not masked so close the connection\n");
|
||||
@@ -77,7 +93,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
return 0;
|
||||
}
|
||||
|
||||
$opcode = $firstbyte & 0xf;
|
||||
$opcode = $first_byte & 0xf;
|
||||
switch ($opcode) {
|
||||
case 0x0:
|
||||
break;
|
||||
@@ -90,12 +106,11 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
// Close package.
|
||||
case 0x8:
|
||||
// Try to emit onWebSocketClose callback.
|
||||
if (isset($connection->onWebSocketClose) || isset($connection->worker->onWebSocketClose)) {
|
||||
$close_cb = $connection->onWebSocketClose ?? $connection->worker->onWebSocketClose ?? false;
|
||||
if ($close_cb) {
|
||||
try {
|
||||
\call_user_func(isset($connection->onWebSocketClose)?$connection->onWebSocketClose:$connection->worker->onWebSocketClose, $connection);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
$close_cb($connection);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
} // Close connection.
|
||||
@@ -109,7 +124,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
// Pong package.
|
||||
case 0xa:
|
||||
break;
|
||||
// Wrong opcode.
|
||||
// Wrong opcode.
|
||||
default :
|
||||
Worker::safeEcho("error opcode $opcode and close websocket connection. Buffer:" . bin2hex($buffer) . "\n");
|
||||
$connection->close();
|
||||
@@ -123,7 +138,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
if ($head_len > $recv_len) {
|
||||
return 0;
|
||||
}
|
||||
$pack = \unpack('nn/ntotal_len', $buffer);
|
||||
$pack = \unpack('nn/ntotal_len', $buffer);
|
||||
$data_len = $pack['total_len'];
|
||||
} else {
|
||||
if ($data_len === 127) {
|
||||
@@ -131,13 +146,13 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
if ($head_len > $recv_len) {
|
||||
return 0;
|
||||
}
|
||||
$arr = \unpack('n/N2c', $buffer);
|
||||
$data_len = $arr['c1']*4294967296 + $arr['c2'];
|
||||
$arr = \unpack('n/N2c', $buffer);
|
||||
$data_len = $arr['c1'] * 4294967296 + $arr['c2'];
|
||||
}
|
||||
}
|
||||
$current_frame_length = $head_len + $data_len;
|
||||
|
||||
$total_package_size = \strlen($connection->websocketDataBuffer) + $current_frame_length;
|
||||
$total_package_size = \strlen($connection->context->websocketDataBuffer) + $current_frame_length;
|
||||
if ($total_package_size > $connection->maxPackageSize) {
|
||||
Worker::safeEcho("error package. package_length=$total_package_size\n");
|
||||
$connection->close();
|
||||
@@ -151,12 +166,11 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
$connection->consumeRecvBuffer($current_frame_length);
|
||||
$tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
|
||||
$connection->websocketType = "\x8a";
|
||||
if (isset($connection->onWebSocketPing) || isset($connection->worker->onWebSocketPing)) {
|
||||
$ping_cb = $connection->onWebSocketPing ?? $connection->worker->onWebSocketPing ?? false;
|
||||
if ($ping_cb) {
|
||||
try {
|
||||
\call_user_func(isset($connection->onWebSocketPing)?$connection->onWebSocketPing:$connection->worker->onWebSocketPing, $connection, $ping_data);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
$ping_cb($connection, $ping_data);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
} else {
|
||||
@@ -175,12 +189,11 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
$tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
|
||||
$connection->websocketType = "\x8a";
|
||||
// Try to emit onWebSocketPong callback.
|
||||
if (isset($connection->onWebSocketPong) || isset($connection->worker->onWebSocketPong)) {
|
||||
$pong_cb = $connection->onWebSocketPong ?? $connection->worker->onWebSocketPong ?? false;
|
||||
if ($pong_cb) {
|
||||
try {
|
||||
\call_user_func(isset($connection->onWebSocketPong)?$connection->onWebSocketPong:$connection->worker->onWebSocketPong, $connection, $pong_data);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
$pong_cb($connection, $pong_data);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
@@ -193,22 +206,22 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
}
|
||||
return $current_frame_length;
|
||||
} else {
|
||||
$connection->websocketCurrentFrameLength = $current_frame_length;
|
||||
$connection->context->websocketCurrentFrameLength = $current_frame_length;
|
||||
}
|
||||
}
|
||||
|
||||
// Received just a frame length data.
|
||||
if ($connection->websocketCurrentFrameLength === $recv_len) {
|
||||
if ($connection->context->websocketCurrentFrameLength === $recv_len) {
|
||||
static::decode($buffer, $connection);
|
||||
$connection->consumeRecvBuffer($connection->websocketCurrentFrameLength);
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
$connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength);
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
return 0;
|
||||
} // The length of the received data is greater than the length of a frame.
|
||||
elseif ($connection->websocketCurrentFrameLength < $recv_len) {
|
||||
static::decode(\substr($buffer, 0, $connection->websocketCurrentFrameLength), $connection);
|
||||
$connection->consumeRecvBuffer($connection->websocketCurrentFrameLength);
|
||||
$current_frame_length = $connection->websocketCurrentFrameLength;
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
elseif ($connection->context->websocketCurrentFrameLength < $recv_len) {
|
||||
static::decode(\substr($buffer, 0, $connection->context->websocketCurrentFrameLength), $connection);
|
||||
$connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength);
|
||||
$current_frame_length = $connection->context->websocketCurrentFrameLength;
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
// Continue to read next frame.
|
||||
return static::input(\substr($buffer, $current_frame_length), $connection);
|
||||
} // The length of the received data is less than the length of a frame.
|
||||
@@ -220,7 +233,7 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
/**
|
||||
* Websocket encode.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param ConnectionInterface $connection
|
||||
* @return string
|
||||
*/
|
||||
@@ -229,12 +242,18 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
if (!is_scalar($buffer)) {
|
||||
throw new \Exception("You can't send(" . \gettype($buffer) . ") to client, you need to convert it to a string. ");
|
||||
}
|
||||
$len = \strlen($buffer);
|
||||
|
||||
if (empty($connection->websocketType)) {
|
||||
$connection->websocketType = static::BINARY_TYPE_BLOB;
|
||||
}
|
||||
|
||||
// permessage-deflate
|
||||
if (\ord($connection->websocketType) & 64) {
|
||||
$buffer = static::deflate($connection, $buffer);
|
||||
}
|
||||
|
||||
$first_byte = $connection->websocketType;
|
||||
$len = \strlen($buffer);
|
||||
|
||||
if ($len <= 125) {
|
||||
$encode_buffer = $first_byte . \chr($len) . $buffer;
|
||||
@@ -247,37 +266,32 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
}
|
||||
|
||||
// Handshake not completed so temporary buffer websocket data waiting for send.
|
||||
if (empty($connection->websocketHandshake)) {
|
||||
if (empty($connection->tmpWebsocketData)) {
|
||||
$connection->tmpWebsocketData = '';
|
||||
if (empty($connection->context->websocketHandshake)) {
|
||||
if (empty($connection->context->tmpWebsocketData)) {
|
||||
$connection->context->tmpWebsocketData = '';
|
||||
}
|
||||
// If buffer has already full then discard the current package.
|
||||
if (\strlen($connection->tmpWebsocketData) > $connection->maxSendBufferSize) {
|
||||
if (\strlen($connection->context->tmpWebsocketData) > $connection->maxSendBufferSize) {
|
||||
if ($connection->onError) {
|
||||
try {
|
||||
\call_user_func($connection->onError, $connection, \WORKERMAN_SEND_FAIL, 'send buffer full and drop package');
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onError)($connection, ConnectionInterface::SEND_FAIL, 'send buffer full and drop package');
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
$connection->tmpWebsocketData .= $encode_buffer;
|
||||
$connection->context->tmpWebsocketData .= $encode_buffer;
|
||||
// Check buffer is full.
|
||||
if ($connection->maxSendBufferSize <= \strlen($connection->tmpWebsocketData)) {
|
||||
if ($connection->maxSendBufferSize <= \strlen($connection->context->tmpWebsocketData)) {
|
||||
if ($connection->onBufferFull) {
|
||||
try {
|
||||
\call_user_func($connection->onBufferFull, $connection);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onBufferFull)($connection);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return empty string.
|
||||
return '';
|
||||
}
|
||||
@@ -288,64 +302,125 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
/**
|
||||
* Websocket decode.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param ConnectionInterface $connection
|
||||
* @return string
|
||||
*/
|
||||
public static function decode($buffer, ConnectionInterface $connection)
|
||||
{
|
||||
$len = \ord($buffer[1]) & 127;
|
||||
$first_byte = \ord($buffer[0]);
|
||||
$second_byte = \ord($buffer[1]);
|
||||
$len = $second_byte & 127;
|
||||
$is_fin_frame = $first_byte >> 7;
|
||||
$rsv1 = 64 === ($first_byte & 64);
|
||||
|
||||
if ($len === 126) {
|
||||
$masks = \substr($buffer, 4, 4);
|
||||
$data = \substr($buffer, 8);
|
||||
$data = \substr($buffer, 8);
|
||||
} else {
|
||||
if ($len === 127) {
|
||||
$masks = \substr($buffer, 10, 4);
|
||||
$data = \substr($buffer, 14);
|
||||
$data = \substr($buffer, 14);
|
||||
} else {
|
||||
$masks = \substr($buffer, 2, 4);
|
||||
$data = \substr($buffer, 6);
|
||||
$data = \substr($buffer, 6);
|
||||
}
|
||||
}
|
||||
$dataLength = \strlen($data);
|
||||
$masks = \str_repeat($masks, \floor($dataLength / 4)) . \substr($masks, 0, $dataLength % 4);
|
||||
$decoded = $data ^ $masks;
|
||||
if ($connection->websocketCurrentFrameLength) {
|
||||
$connection->websocketDataBuffer .= $decoded;
|
||||
return $connection->websocketDataBuffer;
|
||||
if ($connection->context->websocketCurrentFrameLength) {
|
||||
$connection->context->websocketDataBuffer .= $decoded;
|
||||
if ($rsv1) {
|
||||
return static::inflate($connection, $connection->context->websocketDataBuffer, $is_fin_frame);
|
||||
}
|
||||
return $connection->context->websocketDataBuffer;
|
||||
} else {
|
||||
if ($connection->websocketDataBuffer !== '') {
|
||||
$decoded = $connection->websocketDataBuffer . $decoded;
|
||||
$connection->websocketDataBuffer = '';
|
||||
if ($connection->context->websocketDataBuffer !== '') {
|
||||
$decoded = $connection->context->websocketDataBuffer . $decoded;
|
||||
$connection->context->websocketDataBuffer = '';
|
||||
}
|
||||
if ($rsv1) {
|
||||
return static::inflate($connection, $decoded, $is_fin_frame);
|
||||
}
|
||||
return $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflate.
|
||||
*
|
||||
* @param $connection
|
||||
* @param $buffer
|
||||
* @param $is_fin_frame
|
||||
* @return false|string
|
||||
*/
|
||||
protected static function inflate($connection, $buffer, $is_fin_frame)
|
||||
{
|
||||
if (!isset($connection->context->inflator)) {
|
||||
$connection->context->inflator = \inflate_init(
|
||||
\ZLIB_ENCODING_RAW,
|
||||
[
|
||||
'level' => -1,
|
||||
'memory' => 8,
|
||||
'window' => 9,
|
||||
'strategy' => \ZLIB_DEFAULT_STRATEGY
|
||||
]
|
||||
);
|
||||
}
|
||||
if ($is_fin_frame) {
|
||||
$buffer .= "\x00\x00\xff\xff";
|
||||
}
|
||||
return \inflate_add($connection->context->inflator, $buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deflate.
|
||||
*
|
||||
* @param $connection
|
||||
* @param $buffer
|
||||
* @return false|string
|
||||
*/
|
||||
protected static function deflate($connection, $buffer)
|
||||
{
|
||||
if (!isset($connection->context->deflator)) {
|
||||
$connection->context->deflator = \deflate_init(
|
||||
\ZLIB_ENCODING_RAW,
|
||||
[
|
||||
'level' => -1,
|
||||
'memory' => 8,
|
||||
'window' => 9,
|
||||
'strategy' => \ZLIB_DEFAULT_STRATEGY
|
||||
]
|
||||
);
|
||||
}
|
||||
return \substr(\deflate_add($connection->context->deflator, $buffer), 0, -4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Websocket handshake.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param TcpConnection $connection
|
||||
* @return int
|
||||
*/
|
||||
public static function dealHandshake($buffer, TcpConnection $connection)
|
||||
public static function dealHandshake($buffer, $connection)
|
||||
{
|
||||
// HTTP protocol.
|
||||
if (0 === \strpos($buffer, 'GET')) {
|
||||
// Find \r\n\r\n.
|
||||
$heder_end_pos = \strpos($buffer, "\r\n\r\n");
|
||||
if (!$heder_end_pos) {
|
||||
$header_end_pos = \strpos($buffer, "\r\n\r\n");
|
||||
if (!$header_end_pos) {
|
||||
return 0;
|
||||
}
|
||||
$header_length = $heder_end_pos + 4;
|
||||
$header_length = $header_end_pos + 4;
|
||||
|
||||
// Get Sec-WebSocket-Key.
|
||||
$Sec_WebSocket_Key = '';
|
||||
if (\preg_match("/Sec-WebSocket-Key: *(.*?)\r\n/i", $buffer, $match)) {
|
||||
$Sec_WebSocket_Key = $match[1];
|
||||
} else {
|
||||
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/".Worker::VERSION."\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/".Worker::VERSION."</div>",
|
||||
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/" . Worker::VERSION . "\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/" . Worker::VERSION . "</div>",
|
||||
true);
|
||||
return 0;
|
||||
}
|
||||
@@ -353,54 +428,22 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
$new_key = \base64_encode(\sha1($Sec_WebSocket_Key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
|
||||
// Handshake response data.
|
||||
$handshake_message = "HTTP/1.1 101 Switching Protocols\r\n"
|
||||
."Upgrade: websocket\r\n"
|
||||
."Sec-WebSocket-Version: 13\r\n"
|
||||
."Connection: Upgrade\r\n"
|
||||
."Sec-WebSocket-Accept: " . $new_key . "\r\n";
|
||||
. "Upgrade: websocket\r\n"
|
||||
. "Sec-WebSocket-Version: 13\r\n"
|
||||
. "Connection: Upgrade\r\n"
|
||||
. "Sec-WebSocket-Accept: " . $new_key . "\r\n";
|
||||
|
||||
// Websocket data buffer.
|
||||
$connection->websocketDataBuffer = '';
|
||||
$connection->context->websocketDataBuffer = '';
|
||||
// Current websocket frame length.
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
// Current websocket frame data.
|
||||
$connection->websocketCurrentFrameBuffer = '';
|
||||
$connection->context->websocketCurrentFrameBuffer = '';
|
||||
// Consume handshake data.
|
||||
$connection->consumeRecvBuffer($header_length);
|
||||
|
||||
// blob or arraybuffer
|
||||
if (empty($connection->websocketType)) {
|
||||
$connection->websocketType = static::BINARY_TYPE_BLOB;
|
||||
}
|
||||
|
||||
$has_server_header = false;
|
||||
|
||||
if (isset($connection->headers)) {
|
||||
if (\is_array($connection->headers)) {
|
||||
foreach ($connection->headers as $header) {
|
||||
if (\stripos($header, 'Server:') === 0) {
|
||||
$has_server_header = true;
|
||||
}
|
||||
$handshake_message .= "$header\r\n";
|
||||
}
|
||||
} else {
|
||||
if (\stripos($connection->headers, 'Server:') !== false) {
|
||||
$has_server_header = true;
|
||||
}
|
||||
$handshake_message .= "$connection->headers\r\n";
|
||||
}
|
||||
}
|
||||
if (!$has_server_header) {
|
||||
$handshake_message .= "Server: workerman/".Worker::VERSION."\r\n";
|
||||
}
|
||||
$handshake_message .= "\r\n";
|
||||
// Send handshake response.
|
||||
$connection->send($handshake_message, true);
|
||||
// Mark handshake complete..
|
||||
$connection->websocketHandshake = true;
|
||||
|
||||
// Try to emit onWebSocketConnect callback.
|
||||
$on_websocket_connect = isset($connection->onWebSocketConnect) ? $connection->onWebSocketConnect :
|
||||
(isset($connection->worker->onWebSocketConnect) ? $connection->worker->onWebSocketConnect : false);
|
||||
$on_websocket_connect = $connection->onWebSocketConnect ?? $connection->worker->onWebSocketConnect ?? false;
|
||||
if ($on_websocket_connect) {
|
||||
static::parseHttpHeader($buffer);
|
||||
try {
|
||||
@@ -416,24 +459,49 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
$_GET = $_SERVER = $_SESSION = $_COOKIE = array();
|
||||
}
|
||||
|
||||
// blob or arraybuffer
|
||||
if (empty($connection->websocketType)) {
|
||||
$connection->websocketType = static::BINARY_TYPE_BLOB;
|
||||
}
|
||||
|
||||
$has_server_header = false;
|
||||
|
||||
if (isset($connection->headers)) {
|
||||
if (\is_array($connection->headers)) {
|
||||
foreach ($connection->headers as $header) {
|
||||
if (\stripos($header, 'Server:') === 0) {
|
||||
$has_server_header = true;
|
||||
}
|
||||
$handshake_message .= "$header\r\n";
|
||||
}
|
||||
} else {
|
||||
if (\stripos($connection->headers, 'Server:') !== false) {
|
||||
$has_server_header = true;
|
||||
}
|
||||
$handshake_message .= "$connection->headers\r\n";
|
||||
}
|
||||
}
|
||||
if (!$has_server_header) {
|
||||
$handshake_message .= "Server: workerman/" . Worker::VERSION . "\r\n";
|
||||
}
|
||||
$handshake_message .= "\r\n";
|
||||
// Send handshake response.
|
||||
$connection->send($handshake_message, true);
|
||||
// Mark handshake complete..
|
||||
$connection->context->websocketHandshake = true;
|
||||
|
||||
// There are data waiting to be sent.
|
||||
if (!empty($connection->tmpWebsocketData)) {
|
||||
$connection->send($connection->tmpWebsocketData, true);
|
||||
$connection->tmpWebsocketData = '';
|
||||
if (!empty($connection->context->tmpWebsocketData)) {
|
||||
$connection->send($connection->context->tmpWebsocketData, true);
|
||||
$connection->context->tmpWebsocketData = '';
|
||||
}
|
||||
if (\strlen($buffer) > $header_length) {
|
||||
return static::input(\substr($buffer, $header_length), $connection);
|
||||
}
|
||||
return 0;
|
||||
} // Is flash policy-file-request.
|
||||
elseif (0 === \strpos($buffer, '<polic')) {
|
||||
$policy_xml = '<?xml version="1.0"?><cross-domain-policy><site-control permitted-cross-domain-policies="all"/><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>' . "\0";
|
||||
$connection->send($policy_xml, true);
|
||||
$connection->consumeRecvBuffer(\strlen($buffer));
|
||||
return 0;
|
||||
}
|
||||
// Bad websocket handshake request.
|
||||
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/".Worker::VERSION."\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/".Worker::VERSION."</div>",
|
||||
$connection->close("HTTP/1.1 200 WebSocket\r\nServer: workerman/" . Worker::VERSION . "\r\n\r\n<div style=\"text-align:center\"><h1>WebSocket</h1><hr>workerman/" . Worker::VERSION . "</div>",
|
||||
true);
|
||||
return 0;
|
||||
}
|
||||
@@ -492,4 +560,5 @@ class Websocket implements \Workerman\Protocols\ProtocolInterface
|
||||
$_SERVER['QUERY_STRING'] = '';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
318
vendor/workerman/workerman/Protocols/Ws.php
vendored
318
vendor/workerman/workerman/Protocols/Ws.php
vendored
@@ -11,10 +11,11 @@
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Workerman\Protocols;
|
||||
|
||||
use Workerman\Worker;
|
||||
use Workerman\Lib\Timer;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use Workerman\Connection\ConnectionInterface;
|
||||
|
||||
@@ -40,38 +41,38 @@ class Ws
|
||||
/**
|
||||
* Check the integrity of the package.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param ConnectionInterface $connection
|
||||
* @return int
|
||||
*/
|
||||
public static function input($buffer, ConnectionInterface $connection)
|
||||
{
|
||||
if (empty($connection->handshakeStep)) {
|
||||
if (empty($connection->context->handshakeStep)) {
|
||||
Worker::safeEcho("recv data before handshake. Buffer:" . \bin2hex($buffer) . "\n");
|
||||
return false;
|
||||
}
|
||||
// Recv handshake response
|
||||
if ($connection->handshakeStep === 1) {
|
||||
if ($connection->context->handshakeStep === 1) {
|
||||
return self::dealHandshake($buffer, $connection);
|
||||
}
|
||||
$recv_len = \strlen($buffer);
|
||||
if ($recv_len < 2) {
|
||||
$recvLen = \strlen($buffer);
|
||||
if ($recvLen < 2) {
|
||||
return 0;
|
||||
}
|
||||
// Buffer websocket frame data.
|
||||
if ($connection->websocketCurrentFrameLength) {
|
||||
if ($connection->context->websocketCurrentFrameLength) {
|
||||
// We need more frame data.
|
||||
if ($connection->websocketCurrentFrameLength > $recv_len) {
|
||||
if ($connection->context->websocketCurrentFrameLength > $recvLen) {
|
||||
// Return 0, because it is not clear the full packet length, waiting for the frame of fin=1.
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
$firstbyte = \ord($buffer[0]);
|
||||
$secondbyte = \ord($buffer[1]);
|
||||
$data_len = $secondbyte & 127;
|
||||
$is_fin_frame = $firstbyte >> 7;
|
||||
$masked = $secondbyte >> 7;
|
||||
$firstbyte = \ord($buffer[0]);
|
||||
$secondbyte = \ord($buffer[1]);
|
||||
$dataLen = $secondbyte & 127;
|
||||
$isFinFrame = $firstbyte >> 7;
|
||||
$masked = $secondbyte >> 7;
|
||||
|
||||
if ($masked) {
|
||||
Worker::safeEcho("frame masked so close the connection\n");
|
||||
@@ -79,26 +80,26 @@ class Ws
|
||||
return 0;
|
||||
}
|
||||
|
||||
$opcode = $firstbyte & 0xf;
|
||||
$opcode = $firstbyte & 0xf;
|
||||
|
||||
switch ($opcode) {
|
||||
case 0x0:
|
||||
break;
|
||||
// Blob type.
|
||||
// Blob type.
|
||||
case 0x1:
|
||||
break;
|
||||
// Arraybuffer type.
|
||||
// Arraybuffer type.
|
||||
case 0x2:
|
||||
// Ping package.
|
||||
case 0x9:
|
||||
// Pong package.
|
||||
case 0xa:
|
||||
break;
|
||||
// Close package.
|
||||
case 0x8:
|
||||
// Try to emit onWebSocketClose callback.
|
||||
if (isset($connection->onWebSocketClose)) {
|
||||
try {
|
||||
\call_user_func($connection->onWebSocketClose, $connection);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onWebSocketClose)($connection);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
} // Close connection.
|
||||
@@ -106,12 +107,6 @@ class Ws
|
||||
$connection->close();
|
||||
}
|
||||
return 0;
|
||||
// Ping package.
|
||||
case 0x9:
|
||||
break;
|
||||
// Pong package.
|
||||
case 0xa:
|
||||
break;
|
||||
// Wrong opcode.
|
||||
default :
|
||||
Worker::safeEcho("error opcode $opcode and close websocket connection. Buffer:" . $buffer . "\n");
|
||||
@@ -119,96 +114,92 @@ class Ws
|
||||
return 0;
|
||||
}
|
||||
// Calculate packet length.
|
||||
if ($data_len === 126) {
|
||||
if ($dataLen === 126) {
|
||||
if (\strlen($buffer) < 4) {
|
||||
return 0;
|
||||
}
|
||||
$pack = \unpack('nn/ntotal_len', $buffer);
|
||||
$current_frame_length = $pack['total_len'] + 4;
|
||||
} else if ($data_len === 127) {
|
||||
$currentFrameLength = $pack['total_len'] + 4;
|
||||
} else if ($dataLen === 127) {
|
||||
if (\strlen($buffer) < 10) {
|
||||
return 0;
|
||||
}
|
||||
$arr = \unpack('n/N2c', $buffer);
|
||||
$current_frame_length = $arr['c1']*4294967296 + $arr['c2'] + 10;
|
||||
$currentFrameLength = $arr['c1'] * 4294967296 + $arr['c2'] + 10;
|
||||
} else {
|
||||
$current_frame_length = $data_len + 2;
|
||||
$currentFrameLength = $dataLen + 2;
|
||||
}
|
||||
|
||||
$total_package_size = \strlen($connection->websocketDataBuffer) + $current_frame_length;
|
||||
if ($total_package_size > $connection->maxPackageSize) {
|
||||
Worker::safeEcho("error package. package_length=$total_package_size\n");
|
||||
$totalPackageSize = \strlen($connection->context->websocketDataBuffer) + $currentFrameLength;
|
||||
if ($totalPackageSize > $connection->maxPackageSize) {
|
||||
Worker::safeEcho("error package. package_length=$totalPackageSize\n");
|
||||
$connection->close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($is_fin_frame) {
|
||||
if ($isFinFrame) {
|
||||
if ($opcode === 0x9) {
|
||||
if ($recv_len >= $current_frame_length) {
|
||||
$ping_data = static::decode(\substr($buffer, 0, $current_frame_length), $connection);
|
||||
$connection->consumeRecvBuffer($current_frame_length);
|
||||
$tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
|
||||
if ($recvLen >= $currentFrameLength) {
|
||||
$pingData = static::decode(\substr($buffer, 0, $currentFrameLength), $connection);
|
||||
$connection->consumeRecvBuffer($currentFrameLength);
|
||||
$tmpConnectionType = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
|
||||
$connection->websocketType = "\x8a";
|
||||
if (isset($connection->onWebSocketPing)) {
|
||||
try {
|
||||
\call_user_func($connection->onWebSocketPing, $connection, $ping_data);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onWebSocketPing)($connection, $pingData);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
} else {
|
||||
$connection->send($ping_data);
|
||||
$connection->send($pingData);
|
||||
}
|
||||
$connection->websocketType = $tmp_connection_type;
|
||||
if ($recv_len > $current_frame_length) {
|
||||
return static::input(\substr($buffer, $current_frame_length), $connection);
|
||||
$connection->websocketType = $tmpConnectionType;
|
||||
if ($recvLen > $currentFrameLength) {
|
||||
return static::input(\substr($buffer, $currentFrameLength), $connection);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
} else if ($opcode === 0xa) {
|
||||
if ($recv_len >= $current_frame_length) {
|
||||
$pong_data = static::decode(\substr($buffer, 0, $current_frame_length), $connection);
|
||||
$connection->consumeRecvBuffer($current_frame_length);
|
||||
$tmp_connection_type = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
|
||||
if ($recvLen >= $currentFrameLength) {
|
||||
$pongData = static::decode(\substr($buffer, 0, $currentFrameLength), $connection);
|
||||
$connection->consumeRecvBuffer($currentFrameLength);
|
||||
$tmpConnectionType = isset($connection->websocketType) ? $connection->websocketType : static::BINARY_TYPE_BLOB;
|
||||
$connection->websocketType = "\x8a";
|
||||
// Try to emit onWebSocketPong callback.
|
||||
if (isset($connection->onWebSocketPong)) {
|
||||
try {
|
||||
\call_user_func($connection->onWebSocketPong, $connection, $pong_data);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onWebSocketPong)($connection, $pongData);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
$connection->websocketType = $tmp_connection_type;
|
||||
if ($recv_len > $current_frame_length) {
|
||||
return static::input(\substr($buffer, $current_frame_length), $connection);
|
||||
$connection->websocketType = $tmpConnectionType;
|
||||
if ($recvLen > $currentFrameLength) {
|
||||
return static::input(\substr($buffer, $currentFrameLength), $connection);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return $current_frame_length;
|
||||
return $currentFrameLength;
|
||||
} else {
|
||||
$connection->websocketCurrentFrameLength = $current_frame_length;
|
||||
$connection->context->websocketCurrentFrameLength = $currentFrameLength;
|
||||
}
|
||||
}
|
||||
// Received just a frame length data.
|
||||
if ($connection->websocketCurrentFrameLength === $recv_len) {
|
||||
if ($connection->context->websocketCurrentFrameLength === $recvLen) {
|
||||
self::decode($buffer, $connection);
|
||||
$connection->consumeRecvBuffer($connection->websocketCurrentFrameLength);
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
$connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength);
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
return 0;
|
||||
} // The length of the received data is greater than the length of a frame.
|
||||
elseif ($connection->websocketCurrentFrameLength < $recv_len) {
|
||||
self::decode(\substr($buffer, 0, $connection->websocketCurrentFrameLength), $connection);
|
||||
$connection->consumeRecvBuffer($connection->websocketCurrentFrameLength);
|
||||
$current_frame_length = $connection->websocketCurrentFrameLength;
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
elseif ($connection->context->websocketCurrentFrameLength < $recvLen) {
|
||||
self::decode(\substr($buffer, 0, $connection->context->websocketCurrentFrameLength), $connection);
|
||||
$connection->consumeRecvBuffer($connection->context->websocketCurrentFrameLength);
|
||||
$currentFrameLength = $connection->context->websocketCurrentFrameLength;
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
// Continue to read next frame.
|
||||
return self::input(\substr($buffer, $current_frame_length), $connection);
|
||||
return self::input(\substr($buffer, $currentFrameLength), $connection);
|
||||
} // The length of the received data is less than the length of a frame.
|
||||
else {
|
||||
return 0;
|
||||
@@ -218,7 +209,7 @@ class Ws
|
||||
/**
|
||||
* Websocket encode.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param ConnectionInterface $connection
|
||||
* @return string
|
||||
*/
|
||||
@@ -228,52 +219,44 @@ class Ws
|
||||
$connection->websocketType = self::BINARY_TYPE_BLOB;
|
||||
}
|
||||
$payload = (string)$payload;
|
||||
if (empty($connection->handshakeStep)) {
|
||||
if (empty($connection->context->handshakeStep)) {
|
||||
static::sendHandshake($connection);
|
||||
}
|
||||
$mask = 1;
|
||||
$mask_key = "\x00\x00\x00\x00";
|
||||
|
||||
$pack = '';
|
||||
$length = $length_flag = \strlen($payload);
|
||||
if (65535 < $length) {
|
||||
$pack = \pack('NN', ($length & 0xFFFFFFFF00000000) >> 32, $length & 0x00000000FFFFFFFF);
|
||||
$length_flag = 127;
|
||||
} else if (125 < $length) {
|
||||
$pack = \pack('n*', $length);
|
||||
$length_flag = 126;
|
||||
$maskKey = "\x00\x00\x00\x00";
|
||||
$length = \strlen($payload);
|
||||
|
||||
if (strlen($payload) < 126) {
|
||||
$head = chr(0x80 | $length);
|
||||
} elseif ($length < 0xFFFF) {
|
||||
$head = chr(0x80 | 126) . pack("n", $length);
|
||||
} else {
|
||||
$head = chr(0x80 | 127) . pack("N", 0) . pack("N", $length);
|
||||
}
|
||||
|
||||
$head = ($mask << 7) | $length_flag;
|
||||
$head = $connection->websocketType . \chr($head) . $pack;
|
||||
|
||||
$frame = $head . $mask_key;
|
||||
$frame = $connection->websocketType . $head . $maskKey;
|
||||
// append payload to frame:
|
||||
$mask_key = \str_repeat($mask_key, \floor($length / 4)) . \substr($mask_key, 0, $length % 4);
|
||||
$frame .= $payload ^ $mask_key;
|
||||
if ($connection->handshakeStep === 1) {
|
||||
$maskKey = \str_repeat($maskKey, \floor($length / 4)) . \substr($maskKey, 0, $length % 4);
|
||||
$frame .= $payload ^ $maskKey;
|
||||
if ($connection->context->handshakeStep === 1) {
|
||||
// If buffer has already full then discard the current package.
|
||||
if (\strlen($connection->tmpWebsocketData) > $connection->maxSendBufferSize) {
|
||||
if (\strlen($connection->context->tmpWebsocketData) > $connection->maxSendBufferSize) {
|
||||
if ($connection->onError) {
|
||||
try {
|
||||
\call_user_func($connection->onError, $connection, \WORKERMAN_SEND_FAIL, 'send buffer full and drop package');
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onError)($connection, ConnectionInterface::SEND_FAIL, 'send buffer full and drop package');
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
$connection->tmpWebsocketData = $connection->tmpWebsocketData . $frame;
|
||||
$connection->context->tmpWebsocketData = $connection->context->tmpWebsocketData . $frame;
|
||||
// Check buffer is full.
|
||||
if ($connection->maxSendBufferSize <= \strlen($connection->tmpWebsocketData)) {
|
||||
if ($connection->maxSendBufferSize <= \strlen($connection->context->tmpWebsocketData)) {
|
||||
if ($connection->onBufferFull) {
|
||||
try {
|
||||
\call_user_func($connection->onBufferFull, $connection);
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onBufferFull)($connection);
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
@@ -286,30 +269,30 @@ class Ws
|
||||
/**
|
||||
* Websocket decode.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param ConnectionInterface $connection
|
||||
* @return string
|
||||
*/
|
||||
public static function decode($bytes, ConnectionInterface $connection)
|
||||
{
|
||||
$data_length = \ord($bytes[1]);
|
||||
$dataLength = \ord($bytes[1]);
|
||||
|
||||
if ($data_length === 126) {
|
||||
$decoded_data = \substr($bytes, 4);
|
||||
} else if ($data_length === 127) {
|
||||
$decoded_data = \substr($bytes, 10);
|
||||
if ($dataLength === 126) {
|
||||
$decodedData = \substr($bytes, 4);
|
||||
} else if ($dataLength === 127) {
|
||||
$decodedData = \substr($bytes, 10);
|
||||
} else {
|
||||
$decoded_data = \substr($bytes, 2);
|
||||
$decodedData = \substr($bytes, 2);
|
||||
}
|
||||
if ($connection->websocketCurrentFrameLength) {
|
||||
$connection->websocketDataBuffer .= $decoded_data;
|
||||
return $connection->websocketDataBuffer;
|
||||
if ($connection->context->websocketCurrentFrameLength) {
|
||||
$connection->context->websocketDataBuffer .= $decodedData;
|
||||
return $connection->context->websocketDataBuffer;
|
||||
} else {
|
||||
if ($connection->websocketDataBuffer !== '') {
|
||||
$decoded_data = $connection->websocketDataBuffer . $decoded_data;
|
||||
$connection->websocketDataBuffer = '';
|
||||
if ($connection->context->websocketDataBuffer !== '') {
|
||||
$decodedData = $connection->context->websocketDataBuffer . $decodedData;
|
||||
$connection->context->websocketDataBuffer = '';
|
||||
}
|
||||
return $decoded_data;
|
||||
return $decodedData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,13 +313,13 @@ class Ws
|
||||
*/
|
||||
public static function onClose($connection)
|
||||
{
|
||||
$connection->handshakeStep = null;
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
$connection->tmpWebsocketData = '';
|
||||
$connection->websocketDataBuffer = '';
|
||||
if (!empty($connection->websocketPingTimer)) {
|
||||
Timer::del($connection->websocketPingTimer);
|
||||
$connection->websocketPingTimer = null;
|
||||
$connection->context->handshakeStep = null;
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
$connection->context->tmpWebsocketData = '';
|
||||
$connection->context->websocketDataBuffer = '';
|
||||
if (!empty($connection->context->websocketPingTimer)) {
|
||||
Timer::del($connection->context->websocketPingTimer);
|
||||
$connection->context->websocketPingTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,58 +329,57 @@ class Ws
|
||||
* @param TcpConnection $connection
|
||||
* @return void
|
||||
*/
|
||||
public static function sendHandshake(TcpConnection $connection)
|
||||
public static function sendHandshake(ConnectionInterface $connection)
|
||||
{
|
||||
if (!empty($connection->handshakeStep)) {
|
||||
if (!empty($connection->context->handshakeStep)) {
|
||||
return;
|
||||
}
|
||||
// Get Host.
|
||||
$port = $connection->getRemotePort();
|
||||
$host = $port === 80 ? $connection->getRemoteHost() : $connection->getRemoteHost() . ':' . $port;
|
||||
// Handshake header.
|
||||
$connection->websocketSecKey = \base64_encode(random_bytes(16));
|
||||
$user_header = isset($connection->headers) ? $connection->headers :
|
||||
(isset($connection->wsHttpHeader) ? $connection->wsHttpHeader : null);
|
||||
$user_header_str = '';
|
||||
if (!empty($user_header)) {
|
||||
if (\is_array($user_header)){
|
||||
foreach($user_header as $k=>$v){
|
||||
$user_header_str .= "$k: $v\r\n";
|
||||
$connection->context->websocketSecKey = \base64_encode(random_bytes(16));
|
||||
$userHeader = $connection->headers ?? null;
|
||||
$userHeaderStr = '';
|
||||
if (!empty($userHeader)) {
|
||||
if (\is_array($userHeader)) {
|
||||
foreach ($userHeader as $k => $v) {
|
||||
$userHeaderStr .= "$k: $v\r\n";
|
||||
}
|
||||
} else {
|
||||
$user_header_str .= $user_header;
|
||||
$userHeaderStr .= $userHeader;
|
||||
}
|
||||
$user_header_str = "\r\n".\trim($user_header_str);
|
||||
$userHeaderStr = "\r\n" . \trim($userHeaderStr);
|
||||
}
|
||||
$header = 'GET ' . $connection->getRemoteURI() . " HTTP/1.1\r\n".
|
||||
(!\preg_match("/\nHost:/i", $user_header_str) ? "Host: $host\r\n" : '').
|
||||
"Connection: Upgrade\r\n".
|
||||
"Upgrade: websocket\r\n".
|
||||
(isset($connection->websocketOrigin) ? "Origin: ".$connection->websocketOrigin."\r\n":'').
|
||||
(isset($connection->WSClientProtocol)?"Sec-WebSocket-Protocol: ".$connection->WSClientProtocol."\r\n":'').
|
||||
"Sec-WebSocket-Version: 13\r\n".
|
||||
"Sec-WebSocket-Key: " . $connection->websocketSecKey . $user_header_str . "\r\n\r\n";
|
||||
$header = 'GET ' . $connection->getRemoteURI() . " HTTP/1.1\r\n" .
|
||||
(!\preg_match("/\nHost:/i", $userHeaderStr) ? "Host: $host\r\n" : '') .
|
||||
"Connection: Upgrade\r\n" .
|
||||
"Upgrade: websocket\r\n" .
|
||||
(isset($connection->websocketOrigin) ? "Origin: " . $connection->websocketOrigin . "\r\n" : '') .
|
||||
(isset($connection->websocketClientProtocol) ? "Sec-WebSocket-Protocol: " . $connection->websocketClientProtocol . "\r\n" : '') .
|
||||
"Sec-WebSocket-Version: 13\r\n" .
|
||||
"Sec-WebSocket-Key: " . $connection->context->websocketSecKey . $userHeaderStr . "\r\n\r\n";
|
||||
$connection->send($header, true);
|
||||
$connection->handshakeStep = 1;
|
||||
$connection->websocketCurrentFrameLength = 0;
|
||||
$connection->websocketDataBuffer = '';
|
||||
$connection->tmpWebsocketData = '';
|
||||
$connection->context->handshakeStep = 1;
|
||||
$connection->context->websocketCurrentFrameLength = 0;
|
||||
$connection->context->websocketDataBuffer = '';
|
||||
$connection->context->tmpWebsocketData = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Websocket handshake.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param string $buffer
|
||||
* @param TcpConnection $connection
|
||||
* @return int
|
||||
*/
|
||||
public static function dealHandshake($buffer, TcpConnection $connection)
|
||||
public static function dealHandshake($buffer, ConnectionInterface $connection)
|
||||
{
|
||||
$pos = \strpos($buffer, "\r\n\r\n");
|
||||
if ($pos) {
|
||||
//checking Sec-WebSocket-Accept
|
||||
if (\preg_match("/Sec-WebSocket-Accept: *(.*?)\r\n/i", $buffer, $match)) {
|
||||
if ($match[1] !== \base64_encode(\sha1($connection->websocketSecKey . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true))) {
|
||||
if ($match[1] !== \base64_encode(\sha1($connection->context->websocketSecKey . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true))) {
|
||||
Worker::safeEcho("Sec-WebSocket-Accept not match. Header:\n" . \substr($buffer, 0, $pos) . "\n");
|
||||
$connection->close();
|
||||
return 0;
|
||||
@@ -412,49 +394,39 @@ class Ws
|
||||
|
||||
// Get WebSocket subprotocol (if specified by server)
|
||||
if (\preg_match("/Sec-WebSocket-Protocol: *(.*?)\r\n/i", $buffer, $match)) {
|
||||
$connection->WSServerProtocol = \trim($match[1]);
|
||||
$connection->websocketServerProtocol = \trim($match[1]);
|
||||
}
|
||||
|
||||
$connection->handshakeStep = 2;
|
||||
$handshake_response_length = $pos + 4;
|
||||
$connection->context->handshakeStep = 2;
|
||||
$handshakeResponseLength = $pos + 4;
|
||||
// Try to emit onWebSocketConnect callback.
|
||||
if (isset($connection->onWebSocketConnect)) {
|
||||
try {
|
||||
\call_user_func($connection->onWebSocketConnect, $connection, \substr($buffer, 0, $handshake_response_length));
|
||||
} catch (\Exception $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
} catch (\Error $e) {
|
||||
($connection->onWebSocketConnect)($connection, \substr($buffer, 0, $handshakeResponseLength));
|
||||
} catch (\Throwable $e) {
|
||||
Worker::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
// Headbeat.
|
||||
if (!empty($connection->websocketPingInterval)) {
|
||||
$connection->websocketPingTimer = Timer::add($connection->websocketPingInterval, function() use ($connection){
|
||||
$connection->context->websocketPingTimer = Timer::add($connection->websocketPingInterval, function () use ($connection) {
|
||||
if (false === $connection->send(\pack('H*', '898000000000'), true)) {
|
||||
Timer::del($connection->websocketPingTimer);
|
||||
$connection->websocketPingTimer = null;
|
||||
Timer::del($connection->context->websocketPingTimer);
|
||||
$connection->context->websocketPingTimer = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$connection->consumeRecvBuffer($handshake_response_length);
|
||||
if (!empty($connection->tmpWebsocketData)) {
|
||||
$connection->send($connection->tmpWebsocketData, true);
|
||||
$connection->tmpWebsocketData = '';
|
||||
$connection->consumeRecvBuffer($handshakeResponseLength);
|
||||
if (!empty($connection->context->tmpWebsocketData)) {
|
||||
$connection->send($connection->context->tmpWebsocketData, true);
|
||||
$connection->context->tmpWebsocketData = '';
|
||||
}
|
||||
if (\strlen($buffer) > $handshake_response_length) {
|
||||
return self::input(\substr($buffer, $handshake_response_length), $connection);
|
||||
if (\strlen($buffer) > $handshakeResponseLength) {
|
||||
return self::input(\substr($buffer, $handshakeResponseLength), $connection);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static function WSSetProtocol($connection, $params) {
|
||||
$connection->WSClientProtocol = $params[0];
|
||||
}
|
||||
|
||||
public static function WSGetServerProtocol($connection) {
|
||||
return (\property_exists($connection, 'WSServerProtocol') ? $connection->WSServerProtocol : null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
2
vendor/workerman/workerman/README.md
vendored
2
vendor/workerman/workerman/README.md
vendored
@@ -12,7 +12,7 @@ Workerman supports HTTP, Websocket, SSL and other custom protocols.
|
||||
Workerman supports event extension.
|
||||
|
||||
## Requires
|
||||
PHP 5.4 or Higher
|
||||
PHP 7.0 or Higher
|
||||
A POSIX compatible operating system (Linux, OSX, BSD)
|
||||
POSIX and PCNTL extensions required
|
||||
Event extension recommended for better performance
|
||||
|
||||
4
vendor/workerman/workerman/Timer.php
vendored
4
vendor/workerman/workerman/Timer.php
vendored
@@ -210,7 +210,9 @@ class Timer
|
||||
public static function delAll()
|
||||
{
|
||||
self::$_tasks = self::$_status = array();
|
||||
\pcntl_alarm(0);
|
||||
if (\function_exists('pcntl_alarm')) {
|
||||
\pcntl_alarm(0);
|
||||
}
|
||||
if (self::$_event) {
|
||||
self::$_event->clearAllTimer();
|
||||
}
|
||||
|
||||
174
vendor/workerman/workerman/Worker.php
vendored
174
vendor/workerman/workerman/Worker.php
vendored
@@ -34,7 +34,7 @@ class Worker
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const VERSION = '4.1.4';
|
||||
const VERSION = '4.1.9';
|
||||
|
||||
/**
|
||||
* Status starting.
|
||||
@@ -549,8 +549,8 @@ class Worker
|
||||
{
|
||||
static::checkSapiEnv();
|
||||
static::init();
|
||||
static::lock();
|
||||
static::parseCommand();
|
||||
static::lock();
|
||||
static::daemonize();
|
||||
static::initWorkers();
|
||||
static::installSignal();
|
||||
@@ -767,7 +767,7 @@ class Worker
|
||||
protected static function getCurrentUser()
|
||||
{
|
||||
$user_info = \posix_getpwuid(\posix_getuid());
|
||||
return $user_info['name'];
|
||||
return $user_info['name'] ?? 'unknown';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -943,7 +943,7 @@ class Worker
|
||||
exit;
|
||||
}
|
||||
|
||||
$statistics_file = static::$statusFile ? static::$statusFile : __DIR__ . "/../workerman-$master_pid.status";
|
||||
$statistics_file = static::$statusFile ? static::$statusFile : __DIR__ . "/../workerman-$master_pid.$command";
|
||||
|
||||
// execute command.
|
||||
switch ($command) {
|
||||
@@ -1218,7 +1218,7 @@ class Worker
|
||||
case \SIGINT:
|
||||
case \SIGTERM:
|
||||
case \SIGHUP:
|
||||
case \SIGTSTP;
|
||||
case \SIGTSTP:
|
||||
static::$_gracefulStop = false;
|
||||
static::stopAll();
|
||||
break;
|
||||
@@ -1230,6 +1230,9 @@ class Worker
|
||||
// Reload.
|
||||
case \SIGUSR2:
|
||||
case \SIGUSR1:
|
||||
if (static::$_status === static::STATUS_SHUTDOWN || static::$_status === static::STATUS_RELOADING) {
|
||||
return;
|
||||
}
|
||||
static::$_gracefulStop = $signal === \SIGUSR2;
|
||||
static::$_pidsToRestart = static::getAllWorkerPids();
|
||||
static::reload();
|
||||
@@ -1304,7 +1307,7 @@ class Worker
|
||||
$STDOUT = \fopen(static::$stdoutFile, "a");
|
||||
$STDERR = \fopen(static::$stdoutFile, "a");
|
||||
// Fix standard output cannot redirect of PHP 8.1.8's bug
|
||||
if (\posix_isatty(2)) {
|
||||
if (\function_exists('posix_isatty') && \posix_isatty(2)) {
|
||||
\ob_start(function ($string) {
|
||||
\file_put_contents(static::$stdoutFile, $string, FILE_APPEND);
|
||||
}, 1);
|
||||
@@ -1447,11 +1450,39 @@ class Worker
|
||||
/** @var Worker $worker */
|
||||
$worker = current(static::$_workers);
|
||||
|
||||
\Workerman\Timer::delAll();
|
||||
|
||||
//Update process state.
|
||||
static::$_status = static::STATUS_RUNNING;
|
||||
|
||||
// Register shutdown function for checking errors.
|
||||
\register_shutdown_function([__CLASS__, 'checkErrors']);
|
||||
|
||||
// Create a global event loop.
|
||||
if (!static::$globalEvent) {
|
||||
$eventLoopClass = static::getEventLoopName();
|
||||
static::$globalEvent = new $eventLoopClass;
|
||||
}
|
||||
|
||||
// Reinstall signal.
|
||||
static::reinstallSignal();
|
||||
|
||||
// Init Timer.
|
||||
Timer::init(static::$globalEvent);
|
||||
|
||||
\restore_error_handler();
|
||||
|
||||
// Display UI.
|
||||
static::safeEcho(\str_pad($worker->name, 30) . \str_pad($worker->getSocketName(), 36) . \str_pad($worker->count, 10) . "[ok]\n");
|
||||
static::safeEcho(\str_pad($worker->name, 21) . \str_pad($worker->getSocketName(), 36) . \str_pad((string)$worker->count, 10) . "[ok]\n");
|
||||
$worker->listen();
|
||||
$worker->run();
|
||||
exit("@@@child exit@@@\r\n");
|
||||
static::$globalEvent->loop();
|
||||
if (static::$_status !== self::STATUS_SHUTDOWN) {
|
||||
$err = new Exception('event-loop exited');
|
||||
static::log($err);
|
||||
exit(250);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1557,9 +1588,7 @@ class Worker
|
||||
elseif (0 === $pid) {
|
||||
\srand();
|
||||
\mt_srand();
|
||||
if ($worker->reusePort) {
|
||||
$worker->listen();
|
||||
}
|
||||
static::$_gracefulStop = false;
|
||||
if (static::$_status === static::STATUS_STARTING) {
|
||||
static::resetStd();
|
||||
}
|
||||
@@ -1572,10 +1601,32 @@ class Worker
|
||||
}
|
||||
}
|
||||
Timer::delAll();
|
||||
//Update process state.
|
||||
static::$_status = static::STATUS_RUNNING;
|
||||
|
||||
// Register shutdown function for checking errors.
|
||||
\register_shutdown_function(array("\\Workerman\\Worker", 'checkErrors'));
|
||||
|
||||
// Create a global event loop.
|
||||
if (!static::$globalEvent) {
|
||||
$event_loop_class = static::getEventLoopName();
|
||||
static::$globalEvent = new $event_loop_class;
|
||||
}
|
||||
|
||||
// Reinstall signal.
|
||||
static::reinstallSignal();
|
||||
|
||||
// Init Timer.
|
||||
Timer::init(static::$globalEvent);
|
||||
|
||||
\restore_error_handler();
|
||||
|
||||
static::setProcessTitle(self::$processTitle . ': worker process ' . $worker->name . ' ' . $worker->getSocketName());
|
||||
$worker->setUserAndGroup();
|
||||
$worker->id = $id;
|
||||
$worker->run();
|
||||
// Main loop.
|
||||
static::$globalEvent->loop();
|
||||
if (strpos(static::$eventLoopClass, 'Workerman\Events\Swoole') !== false) {
|
||||
exit(0);
|
||||
}
|
||||
@@ -1610,7 +1661,7 @@ class Worker
|
||||
// Get uid.
|
||||
$user_info = \posix_getpwnam($this->user);
|
||||
if (!$user_info) {
|
||||
static::log("Warning: User {$this->user} not exsits");
|
||||
static::log("Warning: User {$this->user} not exists");
|
||||
return;
|
||||
}
|
||||
$uid = $user_info['uid'];
|
||||
@@ -1618,7 +1669,7 @@ class Worker
|
||||
if ($this->group) {
|
||||
$group_info = \posix_getgrnam($this->group);
|
||||
if (!$group_info) {
|
||||
static::log("Warning: Group {$this->group} not exsits");
|
||||
static::log("Warning: Group {$this->group} not exists");
|
||||
return;
|
||||
}
|
||||
$gid = $group_info['gid'];
|
||||
@@ -1689,6 +1740,10 @@ class Worker
|
||||
foreach (static::$_pidMap as $worker_id => $worker_pid_array) {
|
||||
if (isset($worker_pid_array[$pid])) {
|
||||
$worker = static::$_workers[$worker_id];
|
||||
// Fix exit with status 2 for php8.2
|
||||
if ($status === \SIGINT && static::$_status === static::STATUS_SHUTDOWN) {
|
||||
$status = 0;
|
||||
}
|
||||
// Exit status.
|
||||
if ($status !== 0) {
|
||||
static::log("worker[{$worker->name}:$pid] exit with status $status");
|
||||
@@ -1781,6 +1836,11 @@ class Worker
|
||||
{
|
||||
// For master process.
|
||||
if (static::$_masterPid === \posix_getpid()) {
|
||||
if (static::$_gracefulStop) {
|
||||
$sig = \SIGUSR2;
|
||||
} else {
|
||||
$sig = \SIGUSR1;
|
||||
}
|
||||
// Set reloading state.
|
||||
if (static::$_status !== static::STATUS_RELOADING && static::$_status !== static::STATUS_SHUTDOWN) {
|
||||
static::log("Workerman[" . \basename(static::$_startFile) . "] reloading");
|
||||
@@ -1796,32 +1856,27 @@ class Worker
|
||||
}
|
||||
static::initId();
|
||||
}
|
||||
}
|
||||
|
||||
if (static::$_gracefulStop) {
|
||||
$sig = \SIGUSR2;
|
||||
} else {
|
||||
$sig = \SIGUSR1;
|
||||
}
|
||||
|
||||
// Send reload signal to all child processes.
|
||||
$reloadable_pid_array = array();
|
||||
foreach (static::$_pidMap as $worker_id => $worker_pid_array) {
|
||||
$worker = static::$_workers[$worker_id];
|
||||
if ($worker->reloadable) {
|
||||
foreach ($worker_pid_array as $pid) {
|
||||
$reloadable_pid_array[$pid] = $pid;
|
||||
}
|
||||
} else {
|
||||
foreach ($worker_pid_array as $pid) {
|
||||
// Send reload signal to a worker process which reloadable is false.
|
||||
\posix_kill($pid, $sig);
|
||||
// Send reload signal to all child processes.
|
||||
$reloadable_pid_array = array();
|
||||
foreach (static::$_pidMap as $worker_id => $worker_pid_array) {
|
||||
$worker = static::$_workers[$worker_id];
|
||||
if ($worker->reloadable) {
|
||||
foreach ($worker_pid_array as $pid) {
|
||||
$reloadable_pid_array[$pid] = $pid;
|
||||
}
|
||||
} else {
|
||||
foreach ($worker_pid_array as $pid) {
|
||||
// Send reload signal to a worker process which reloadable is false.
|
||||
\posix_kill($pid, $sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get all pids that are waiting reload.
|
||||
static::$_pidsToRestart = \array_intersect(static::$_pidsToRestart, $reloadable_pid_array);
|
||||
// Get all pids that are waiting reload.
|
||||
static::$_pidsToRestart = \array_intersect(static::$_pidsToRestart, $reloadable_pid_array);
|
||||
|
||||
}
|
||||
|
||||
// Reload complete.
|
||||
if (empty(static::$_pidsToRestart)) {
|
||||
@@ -1883,7 +1938,11 @@ class Worker
|
||||
$sig = \SIGINT;
|
||||
}
|
||||
foreach ($worker_pid_array as $worker_pid) {
|
||||
\posix_kill($worker_pid, $sig);
|
||||
if (static::$daemonize) {
|
||||
\posix_kill($worker_pid, $sig);
|
||||
} else {
|
||||
Timer::add(1, '\posix_kill', array($worker_pid, $sig), false);
|
||||
}
|
||||
if(!static::$_gracefulStop){
|
||||
Timer::add(static::$stopTimeout, '\posix_kill', array($worker_pid, \SIGKILL), false);
|
||||
}
|
||||
@@ -1896,7 +1955,8 @@ class Worker
|
||||
} // For child processes.
|
||||
else {
|
||||
// Execute exit.
|
||||
foreach (static::$_workers as $worker) {
|
||||
$workers = array_reverse(static::$_workers);
|
||||
foreach ($workers as $worker) {
|
||||
if(!$worker->stopping){
|
||||
$worker->stop();
|
||||
$worker->stopping = true;
|
||||
@@ -2416,37 +2476,11 @@ class Worker
|
||||
* Run worker instance.
|
||||
*
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
//Update process state.
|
||||
static::$_status = static::STATUS_RUNNING;
|
||||
|
||||
// Register shutdown function for checking errors.
|
||||
\register_shutdown_function(array("\\Workerman\\Worker", 'checkErrors'));
|
||||
|
||||
// Set autoload root path.
|
||||
Autoloader::setRootPath($this->_autoloadRootPath);
|
||||
|
||||
// Create a global event loop.
|
||||
if (!static::$globalEvent) {
|
||||
$event_loop_class = static::getEventLoopName();
|
||||
static::$globalEvent = new $event_loop_class;
|
||||
$this->resumeAccept();
|
||||
}
|
||||
|
||||
// Reinstall signal.
|
||||
static::reinstallSignal();
|
||||
|
||||
// Init Timer.
|
||||
Timer::init(static::$globalEvent);
|
||||
|
||||
// Set an empty onMessage callback.
|
||||
if (empty($this->onMessage)) {
|
||||
$this->onMessage = function () {};
|
||||
}
|
||||
|
||||
\restore_error_handler();
|
||||
$this->listen();
|
||||
|
||||
// Try to emit onWorkerStart callback.
|
||||
if ($this->onWorkerStart) {
|
||||
@@ -2462,9 +2496,6 @@ class Worker
|
||||
static::stopAll(250, $e);
|
||||
}
|
||||
}
|
||||
|
||||
// Main loop.
|
||||
static::$globalEvent->loop();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2492,6 +2523,13 @@ class Worker
|
||||
$connection->close();
|
||||
}
|
||||
}
|
||||
// Remove worker.
|
||||
foreach(static::$_workers as $key => $one_worker) {
|
||||
if ($one_worker->workerId === $this->workerId) {
|
||||
unset(static::$_workers[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear callback.
|
||||
$this->onMessage = $this->onClose = $this->onError = $this->onBufferDrain = $this->onBufferFull = null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user