改名
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Exception;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class BaseAnnotation
|
||||
* @package Snowflake\Snowflake\Annotation\Base
|
||||
*/
|
||||
abstract class BaseAnnotation extends Component
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param ReflectionClass $reflect
|
||||
* @param string $method
|
||||
* @param array $annotations
|
||||
* @return array
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function instance($reflect, $method = '', $annotations = [])
|
||||
{
|
||||
$classMethods = $reflect->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
if (!$reflect->isInstantiable()) {
|
||||
throw new Exception('Class ' . $reflect->getName() . ' cannot be instantiated.');
|
||||
}
|
||||
|
||||
$array = [];
|
||||
$object = $reflect->newInstance();
|
||||
if (!empty($method)) {
|
||||
$array = $this->resolveDocComment($reflect->getMethod($method), $object, $annotations, $array);
|
||||
} else {
|
||||
foreach ($classMethods as $classMethod) {
|
||||
$array = $this->resolveDocComment($classMethod, $object, $annotations, $array);
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ReflectionMethod $function
|
||||
* @param $object
|
||||
* @param $annotations
|
||||
* @param $array
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
protected function resolveDocComment($function, $object, $annotations, $array)
|
||||
{
|
||||
$comment = $function->getDocComment();
|
||||
$array = $this->getDocCommentAnnotation($annotations, $comment);
|
||||
foreach ($array as $name => $annotation) {
|
||||
foreach ($annotation as $index => $events) {
|
||||
if (!isset($events[1])) {
|
||||
continue;
|
||||
}
|
||||
if (!($_key = $this->getName($name, $events))) {
|
||||
continue;
|
||||
}
|
||||
if (isset($item[2])) {
|
||||
$handler = Snowflake::createObject($events[2]);
|
||||
} else {
|
||||
$handler = [$object, $events[1]];
|
||||
}
|
||||
if (!isset($array[$annotation])) {
|
||||
$array[$annotation] = [];
|
||||
}
|
||||
$array[$name][] = [$_key, $handler];
|
||||
}
|
||||
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $object
|
||||
* @param $events
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function getOrCreate($object, $events)
|
||||
{
|
||||
if (isset($item[2])) {
|
||||
$handler = Snowflake::createObject($events[2]);
|
||||
} else {
|
||||
$handler = [$object, $events[1]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $annotations
|
||||
* @param $comment
|
||||
* @return array
|
||||
*/
|
||||
protected function getDocCommentAnnotation($annotations, $comment)
|
||||
{
|
||||
$array = [];
|
||||
foreach ($annotations as $annotation) {
|
||||
preg_match('/@(' . $annotation . ')\((.*?)\)/', $comment, $events);
|
||||
if (!isset($events[1])) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($array[$annotation])) {
|
||||
$array[$annotation] = [];
|
||||
}
|
||||
$array[$annotation] = [$annotation, $events];
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $rule
|
||||
* @param $content
|
||||
* @param $rules
|
||||
* @return bool
|
||||
* @throws ReflectionException
|
||||
* @throws NotFindClassException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function check($rule, $content, $rules)
|
||||
{
|
||||
if (empty($rule)) {
|
||||
return true;
|
||||
}
|
||||
$explode = explode('|', $rule);
|
||||
foreach ($explode as $value) {
|
||||
$reflect = array_merge($rules[$value], [
|
||||
'value' => $content
|
||||
]);
|
||||
$validator = Snowflake::createObject($reflect);
|
||||
if (!$validator->check()) {
|
||||
throw new Exception($validator->getMessage());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
abstract public function runWith($path);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/10/7 0007
|
||||
* Time: 2:13
|
||||
*/
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Http\Request;
|
||||
use HttpServer\Http\Response;
|
||||
use HttpServer\Route\Router;
|
||||
use HttpServer\Server;
|
||||
use Snowflake\Annotation\Annotation;
|
||||
use Snowflake\Cache\Memcached;
|
||||
use Snowflake\Cache\Redis;
|
||||
use Snowflake\Config;
|
||||
use Snowflake\Di\Service;
|
||||
use Snowflake\Error\ErrorHandler;
|
||||
use Snowflake\Error\Logger;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Exception\InitException;
|
||||
use Snowflake\Jwt\Jwt;
|
||||
use Snowflake\Pool\Connection;
|
||||
use Snowflake\Pool\Redis as SRedis;
|
||||
use Snowflake\Snowflake;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Pool\Pool as SPool;
|
||||
use Database\DatabasesProviders;
|
||||
|
||||
/**
|
||||
* Class BaseApplication
|
||||
* @package Snowflake\Snowflake\Base
|
||||
* @property $json
|
||||
* @property Annotation $annotation
|
||||
* @property Event $event
|
||||
* @property Router $router
|
||||
* @property SPool $pool
|
||||
* @property Server $server
|
||||
* @property DatabasesProviders $db
|
||||
* @property Connection $connections
|
||||
* @property Memcached $memcached
|
||||
* @property Logger $logger
|
||||
* @property Jwt $jwt
|
||||
*/
|
||||
abstract class BaseApplication extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $storage = APP_PATH . '/storage';
|
||||
|
||||
public $envPath = APP_PATH . '/.env';
|
||||
|
||||
/**
|
||||
* Init constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @throws
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
Snowflake::init($this);
|
||||
|
||||
$this->moreComponents();
|
||||
$this->parseInt($config);
|
||||
$this->initErrorHandler();
|
||||
$this->enableEnvConfig();
|
||||
|
||||
Component::__construct($config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function enableEnvConfig()
|
||||
{
|
||||
if (!file_exists($this->envPath)) {
|
||||
return [];
|
||||
}
|
||||
$lines = $this->readLinesFromFile($this->envPath);
|
||||
foreach ($lines as $line) {
|
||||
if (!$this->isComment($line) && $this->looksLikeSetter($line)) {
|
||||
[$key, $value] = explode('=', $line);
|
||||
putenv(trim($key) . '=' . trim($value));
|
||||
}
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read lines from the file, auto detecting line endings.
|
||||
*
|
||||
* @param string $filePath
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function readLinesFromFile($filePath)
|
||||
{
|
||||
// Read file into an array of lines with auto-detected line endings
|
||||
$autodetect = ini_get('auto_detect_line_endings');
|
||||
ini_set('auto_detect_line_endings', '1');
|
||||
$lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
ini_set('auto_detect_line_endings', $autodetect);
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the line in the file is a comment, e.g. begins with a #.
|
||||
*
|
||||
* @param string $line
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isComment($line)
|
||||
{
|
||||
$line = ltrim($line);
|
||||
|
||||
return isset($line[0]) && $line[0] === '#';
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given line looks like it's setting a variable.
|
||||
*
|
||||
* @param string $line
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function looksLikeSetter($line)
|
||||
{
|
||||
return strpos($line, '=') !== false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $config
|
||||
*
|
||||
* @throws
|
||||
*/
|
||||
public function parseInt($config)
|
||||
{
|
||||
foreach ($config as $key => $value) {
|
||||
Config::set($key, $value);
|
||||
}
|
||||
if ($storage = Config::get('storage', false, 'storage')) {
|
||||
if (strpos($storage, APP_PATH) === false) {
|
||||
$storage = APP_PATH . $storage . '/';
|
||||
}
|
||||
if (!is_dir($storage)) {
|
||||
mkdir($storage);
|
||||
}
|
||||
if (!is_dir($storage) || !is_writeable($storage)) {
|
||||
throw new InitException("Directory {$storage} does not have write permission");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function clone($name)
|
||||
{
|
||||
return clone $this->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function initErrorHandler()
|
||||
{
|
||||
$this->get('error')->register();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLocalIps()
|
||||
{
|
||||
return swoole_get_local_ip();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFirstLocal()
|
||||
{
|
||||
return current($this->getLocalIps());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Logger
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getLogger(): Logger
|
||||
{
|
||||
return $this->get('logger');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Redis
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getRedis()
|
||||
{
|
||||
return $this->get('redis');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $ip
|
||||
* @return bool
|
||||
*/
|
||||
public function isLocal($ip)
|
||||
{
|
||||
return $this->getFirstLocal() == $ip;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ErrorHandler
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->get('error');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Annotation
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getAnnotation()
|
||||
{
|
||||
return $this->get('annotation');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Connection
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getConnections()
|
||||
{
|
||||
return $this->get('connections');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Pool
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getPool()
|
||||
{
|
||||
return $this->get('pool');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Response
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->get('response');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Request
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->get('request');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Config
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->get('config');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Router
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getRouter()
|
||||
{
|
||||
return $this->get('router');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Event
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getEvent()
|
||||
{
|
||||
return $this->get('event');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Jwt
|
||||
* @throws ComponentException
|
||||
*/
|
||||
public function getJwt()
|
||||
{
|
||||
return $this->get('jwt');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function moreComponents()
|
||||
{
|
||||
return $this->setComponents([
|
||||
'error' => ['class' => ErrorHandler::class],
|
||||
'event' => ['class' => Event::class],
|
||||
'annotation' => ['class' => Annotation::class],
|
||||
'connections' => ['class' => Connection::class],
|
||||
'redis_connections' => ['class' => SRedis::class],
|
||||
'pool' => ['class' => SPool::class],
|
||||
'response' => ['class' => Response::class],
|
||||
'request' => ['class' => Request::class],
|
||||
'config' => ['class' => Config::class],
|
||||
'logger' => ['class' => Logger::class],
|
||||
'router' => ['class' => Router::class],
|
||||
'redis' => ['class' => Redis::class],
|
||||
'jwt' => ['class' => Jwt::class]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:10
|
||||
*/
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Error\Logger;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class BaseObject
|
||||
* @method defer()
|
||||
* @package Snowflake\Snowflake\Base
|
||||
* @method afterInit
|
||||
* @method initialization
|
||||
*/
|
||||
class BaseObject implements Configure
|
||||
{
|
||||
|
||||
/**
|
||||
* BaseAbstract constructor.
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
if (!empty($config) && is_array($config)) {
|
||||
Snowflake::configure($this, $config);
|
||||
}
|
||||
$this->init();
|
||||
}
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function className()
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$method = 'set' . ucfirst($name);
|
||||
if (method_exists($this, $method)) {
|
||||
$this->{$method}($value);
|
||||
} else {
|
||||
$this->error('set ' . $name . ' not exists ' . get_called_class());
|
||||
throw new Exception('The set name ' . $name . ' not find in class ' . get_class($this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
$method = 'get' . ucfirst($name);
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->$method();
|
||||
} else {
|
||||
throw new Exception('The get name ' . $name . ' not find in class ' . get_class($this));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
*
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if (!method_exists($this, $name)) {
|
||||
throw new Exception("Not find " . get_called_class() . "::($name)");
|
||||
} else {
|
||||
$result = $this->$name(...$arguments);
|
||||
if (method_exists($this, 'defer')) {
|
||||
$this->defer();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $model
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addError($message, $model = 'app')
|
||||
{
|
||||
if ($message instanceof Exception) {
|
||||
$this->error($message->getMessage(), $message->getFile(), $message->getLine());
|
||||
} else {
|
||||
if (!is_string($message)) {
|
||||
$message = json_encode($message, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$this->error($message);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string $method
|
||||
* @param string $file
|
||||
* @throws
|
||||
*/
|
||||
public function debug($message, string $method = __METHOD__, string $file = __FILE__)
|
||||
{
|
||||
if (!is_string($message)) {
|
||||
$message = print_r($message, true);
|
||||
}
|
||||
echo "\033[35m[DEBUG][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string $method
|
||||
* @param string $file
|
||||
* @throws
|
||||
*/
|
||||
public function info($message, string $method = __METHOD__, string $file = __FILE__)
|
||||
{
|
||||
if (!is_string($message)) {
|
||||
$message = print_r($message, true);
|
||||
}
|
||||
echo "\033[34m[INFO][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string $method
|
||||
* @param string $file
|
||||
* @throws
|
||||
*/
|
||||
public function success($message, string $method = __METHOD__, string $file = __FILE__)
|
||||
{
|
||||
if (!is_string($message)) {
|
||||
$message = print_r($message, true);
|
||||
}
|
||||
echo "\033[36m[SUCCESS][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string $method
|
||||
* @param string $file
|
||||
* @throws
|
||||
*/
|
||||
public function warning($message, string $method = __METHOD__, string $file = __FILE__)
|
||||
{
|
||||
if (!is_string($message)) {
|
||||
$message = print_r($message, true);
|
||||
}
|
||||
echo "\033[33m[SUCCESS][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string|null $method
|
||||
* @param string|null $file
|
||||
* @throws Exception
|
||||
*/
|
||||
public function error($message, $method = null, $file = null)
|
||||
{
|
||||
if (!empty($file)) {
|
||||
echo "\033[41;37m[ERROR][" . date('Y-m-d H:i:s') . ']: ' . $file . "\033[0m";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
if (!is_string($message)) {
|
||||
$message = print_r($message, true);
|
||||
}
|
||||
echo "\033[41;37m[ERROR][" . date('Y-m-d H:i:s') . ']: ' . (empty($method) ? '' : $method . ': ') . $message . "\033[0m";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:28
|
||||
*/
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Component
|
||||
* @package Snowflake\Snowflake\Base
|
||||
*/
|
||||
class Component extends BaseObject
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_events = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param $name [事件名称]
|
||||
* @param $callback [回调函数]
|
||||
* @param array $param [函数参数]
|
||||
*
|
||||
* {
|
||||
* 事件名, 回调, 参数
|
||||
* }
|
||||
*/
|
||||
public function on($name, $callback, $param = [])
|
||||
{
|
||||
if (isset($this->_events[$name])) {
|
||||
array_push($this->_events[$name], [$callback, $param]);
|
||||
} else {
|
||||
$this->_events[$name][] = [$callback, $param];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function hasEvent($name, $callback = null)
|
||||
{
|
||||
if (!isset($this->_events[$name])) {
|
||||
return false;
|
||||
}
|
||||
if (!is_array($this->_events[$name])) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->_events[$name] as $event) {
|
||||
[$_callback, $param] = $event;
|
||||
if ($_callback === $callback) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $event
|
||||
* @param array $params
|
||||
* @param bool $isRemove
|
||||
* @throws Exception
|
||||
*/
|
||||
public function trigger($name, $event = null, $params = [], $isRemove = false)
|
||||
{
|
||||
$aEvents = Snowflake::app()->event;
|
||||
if (isset($this->_events[$name])) {
|
||||
$events = $this->_events[$name];
|
||||
foreach ($events as $key => $_event) {
|
||||
if (!empty($event)) {
|
||||
$_event = $event;
|
||||
}
|
||||
call_user_func($_event, ...$params);
|
||||
if ($isRemove) {
|
||||
unset($this->_events[$name][$key]);
|
||||
$aEvents->of($name, $_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
$aEvents->trigger($name, $event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $handler
|
||||
* @return mixed
|
||||
*/
|
||||
public function off($name, $handler = NULL)
|
||||
{
|
||||
$aEvents = Snowflake::app()->event;
|
||||
if (!isset($this->_events[$name])) {
|
||||
return $aEvents->of($name, $handler);
|
||||
}
|
||||
|
||||
if (empty($handler)) {
|
||||
unset($this->_events[$name]);
|
||||
|
||||
return $aEvents->of($name, $handler);
|
||||
}
|
||||
|
||||
foreach ($this->_events[$name] as $key => $val) {
|
||||
if ($val[0] != $handler) {
|
||||
continue;
|
||||
}
|
||||
unset($this->_events[$name][$key]);
|
||||
|
||||
break;
|
||||
}
|
||||
return $aEvents->of($name, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function offAll()
|
||||
{
|
||||
$this->_events = [];
|
||||
$aEvents = Snowflake::app()->event;
|
||||
$aEvents->clean();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if (property_exists($this, $name)) {
|
||||
$this->$name = $value;
|
||||
} else {
|
||||
parent::__set($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (property_exists($this, $name)) {
|
||||
return $this->$name ?? null;
|
||||
} else {
|
||||
return parent::__get($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/5/24 0024
|
||||
* Time: 11:50
|
||||
*/
|
||||
|
||||
namespace Snowflake;
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
|
||||
/**
|
||||
* Class Config
|
||||
* @package Snowflake\Snowflake\Base
|
||||
*/
|
||||
class Config extends Component
|
||||
{
|
||||
|
||||
const ERROR_MESSAGE = 'The not find %s in app configs.';
|
||||
|
||||
protected $data;
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function setData($key, $value)
|
||||
{
|
||||
return $this->data[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param bool $try
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
* @throws
|
||||
*/
|
||||
public static function get($key, $try = FALSE, $default = null)
|
||||
{
|
||||
$explode = explode('.', $key);
|
||||
$instance = Snowflake::app()->config->getData();
|
||||
foreach ($explode as $index => $value) {
|
||||
if (empty($value)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($instance[$value])) {
|
||||
if ($try) {
|
||||
throw new ConfigException(sprintf(self::ERROR_MESSAGE, $key));
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
$instance = $instance[$value];
|
||||
if (!is_array($instance) && $index + 1 < count($explode)) {
|
||||
throw new ConfigException(sprintf(self::ERROR_MESSAGE, $key));
|
||||
}
|
||||
}
|
||||
return empty($instance) ? $default : $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function set($key, $value)
|
||||
{
|
||||
$config = Snowflake::app()->config;
|
||||
return $config->setData($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param bool $must_not_null
|
||||
* @return bool
|
||||
*/
|
||||
public static function has($key, $must_not_null = false)
|
||||
{
|
||||
$config = Snowflake::app()->config;
|
||||
if (!isset($config->data[$key])) {
|
||||
return false;
|
||||
}
|
||||
$config = $config->data[$key];
|
||||
if ($must_not_null === false) {
|
||||
return true;
|
||||
}
|
||||
return !empty($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->data[$name] = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:11
|
||||
*/
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
/**
|
||||
* Interface Configure
|
||||
* @package Snowflake\Snowflake\Base
|
||||
*/
|
||||
interface Configure
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Snowflake\Core\Dtl;
|
||||
|
||||
interface IListener
|
||||
{
|
||||
|
||||
|
||||
public function handler(Dtl $dtl);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
/**
|
||||
* Class Listener
|
||||
* @package Snowflake\Abstracts
|
||||
* 监听的名称
|
||||
*/
|
||||
abstract class Listener extends Component implements IListener
|
||||
{
|
||||
|
||||
protected $trigger = '';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Swoole\Coroutine;
|
||||
use Swoole\Coroutine\Channel;
|
||||
|
||||
/**
|
||||
* Class Pool
|
||||
* @package Snowflake\Snowflake\Pool
|
||||
*/
|
||||
abstract class Pool extends Component
|
||||
{
|
||||
|
||||
/** @var Channel[] */
|
||||
private $_items = [];
|
||||
|
||||
public $max = 60;
|
||||
|
||||
private $is_ticker = false;
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param false $isMaster
|
||||
* @param int $max
|
||||
*/
|
||||
public function initConnections($name, $isMaster = false, $max = 60)
|
||||
{
|
||||
$name = $this->name($name, $isMaster);
|
||||
if (isset($this->_items[$name]) &&
|
||||
$this->_items[$name] instanceof Channel) {
|
||||
return;
|
||||
}
|
||||
$this->_items[$name] = new Channel($max);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param int $timeout
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function get($name, $timeout = -1)
|
||||
{
|
||||
if ($this->is_ticker) {
|
||||
Coroutine::sleep(1);
|
||||
}
|
||||
if ($timeout != -1) {
|
||||
$client = $this->_items[$name]->pop($timeout);
|
||||
} else {
|
||||
$client = $this->_items[$name]->pop(60);
|
||||
}
|
||||
if (!$this->checkCanUse(...$client)) {
|
||||
unset($client);
|
||||
return [0, null];
|
||||
} else {
|
||||
return $client;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cds
|
||||
* @param false $isMaster
|
||||
* @return string
|
||||
*/
|
||||
public function name($cds, $isMaster = false)
|
||||
{
|
||||
return hash('sha1', $cds . ($isMaster ? 'master' : 'slave'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $time
|
||||
* @param $client
|
||||
* @return mixed
|
||||
* 检查连接可靠性
|
||||
* @throws Exception
|
||||
*/
|
||||
public function checkCanUse($time, $client)
|
||||
{
|
||||
throw new Exception('Undefined system processing function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @throws Exception
|
||||
*/
|
||||
public function desc($name)
|
||||
{
|
||||
throw new Exception('Undefined system processing function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param $isMaster
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnection(array $config, $isMaster)
|
||||
{
|
||||
throw new Exception('Undefined system processing function.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasItem($name)
|
||||
{
|
||||
return $this->hasLength($name) > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasLength($name)
|
||||
{
|
||||
if (!isset($this->_items[$name])) {
|
||||
return 0;
|
||||
}
|
||||
return $this->_items[$name]->length();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $client
|
||||
*/
|
||||
public function push($name, $client)
|
||||
{
|
||||
if (!isset($this->_items[$name])) {
|
||||
return;
|
||||
}
|
||||
if (!$this->_items[$name]->isFull()) {
|
||||
$this->_items[$name]->push([time(), $client]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
*/
|
||||
public function clean($name)
|
||||
{
|
||||
if (!isset($this->_items[$name])) {
|
||||
return;
|
||||
}
|
||||
while ([$time, $client] = $this->_items[$name]->pop(0.001)) {
|
||||
unset($client);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Snowflake\Application;
|
||||
|
||||
interface Provider
|
||||
{
|
||||
|
||||
public function onImport(Application $application);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Abstracts;
|
||||
|
||||
|
||||
use Snowflake\Application;
|
||||
|
||||
/**
|
||||
* Class Providers
|
||||
* @package Snowflake\Abstracts
|
||||
*/
|
||||
abstract class Providers extends Component implements Provider
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Annotation;
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Route\Annotation\Websocket;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
use Snowflake\Abstracts\BaseAnnotation;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
use validator\RequiredValidator;
|
||||
use validator\RequiredValidator as NotEmptyValidator;
|
||||
|
||||
/**
|
||||
* Class Annotation
|
||||
* @package Snowflake\Snowflake\Annotation
|
||||
*/
|
||||
class Annotation extends BaseAnnotation
|
||||
{
|
||||
public $namespace = '';
|
||||
|
||||
public $prefix = '';
|
||||
|
||||
public $path = '';
|
||||
|
||||
|
||||
protected $_Scan_directory = [];
|
||||
|
||||
protected $_alias = [];
|
||||
|
||||
protected $params = [];
|
||||
|
||||
|
||||
private $_classMap = [];
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $class
|
||||
* @return mixed
|
||||
* @throws
|
||||
*/
|
||||
public function register($name, $class)
|
||||
{
|
||||
if (!isset($this->_classMap[$name]) || is_string($this->_classMap[$name])) {
|
||||
$this->_classMap[$name] = Snowflake::createObject($class);
|
||||
}
|
||||
return $this->_classMap[$name];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $namespace
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function registration_notes($path = '', $namespace = '')
|
||||
{
|
||||
if (empty($path)) {
|
||||
$path = $this->path;
|
||||
}
|
||||
if (empty($namespace)) {
|
||||
$namespace = $this->namespace;
|
||||
}
|
||||
$this->scanning(rtrim($path, '/'), $namespace, get_called_class());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReflectionClass $reflect
|
||||
* @param string $className
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
* @Message(updatePosition)
|
||||
* 注入注解
|
||||
*/
|
||||
private function resolve(ReflectionClass $reflect, string $className)
|
||||
{
|
||||
$controller = $reflect->newInstance();
|
||||
|
||||
$annotations = $this->getAnnotation($className);
|
||||
$methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $function) {
|
||||
foreach ($annotations as $annotation) {
|
||||
$comment = $function->getDocComment();
|
||||
$methodName = $function->getName();
|
||||
|
||||
preg_match('/@(' . $annotation . ')\((.*?)\)/', $comment, $events);
|
||||
if (!isset($events[1])) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->isLegitimate($events)) {
|
||||
continue;
|
||||
}
|
||||
$this->push($this->getName($annotation, $events), [$controller, $methodName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (!isset($this->_classMap[$name])) {
|
||||
throw new Exception('Undefined analytic class ' . $name . '.');
|
||||
}
|
||||
return $this->_classMap[$name];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $events
|
||||
* @throws Exception
|
||||
*/
|
||||
public function isLegitimate($events)
|
||||
{
|
||||
throw new Exception('Undefined analytic function isLegitimate.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $function
|
||||
* @param $events
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getName($function, $events)
|
||||
{
|
||||
throw new Exception('Undefined analytic function getName.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $controller
|
||||
* @param $methodName
|
||||
* @param $events
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createHandler($controller, $methodName, $events)
|
||||
{
|
||||
throw new Exception('Undefined analytic function.');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param $namespace
|
||||
* @param $className
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected function scanning($path, $namespace, $className)
|
||||
{
|
||||
$di = Snowflake::getDi();
|
||||
foreach (glob($path . '/*') as $file) {
|
||||
if (is_dir($file)) {
|
||||
$this->scanning($path, $namespace, $className);
|
||||
}
|
||||
|
||||
$explode = explode('/', $file);
|
||||
|
||||
$class = str_replace('.php', '', end($explode));
|
||||
|
||||
$this->resolve($di->getReflect($namespace . '\\' . $class), $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function runWith($path, $params = [])
|
||||
{
|
||||
if (!$this->has($path)) {
|
||||
return null;
|
||||
}
|
||||
$callback = $this->_Scan_directory[$path];
|
||||
if (!isset($this->params[$path])) {
|
||||
return $callback(...$params);
|
||||
}
|
||||
return $callback(...$this->params[$path]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $callback
|
||||
* @param array $params
|
||||
*/
|
||||
public function push($name, $callback, $params = [])
|
||||
{
|
||||
$this->_Scan_directory[$name] = $callback;
|
||||
if (!empty($params)) {
|
||||
$this->params[$name] = $params;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return array|null[]
|
||||
*/
|
||||
public function pop($name)
|
||||
{
|
||||
if (isset($this->_Scan_directory[$name])) {
|
||||
return [$this->_Scan_directory[$name], $this->params[$name] ?? []];
|
||||
}
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function has($path)
|
||||
{
|
||||
return isset($this->_Scan_directory[$path]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed|null
|
||||
* @throws ReflectionException
|
||||
* @throws NotFindClassException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (!isset($this->_classMap[$name])) {
|
||||
return parent::__get($name); // TODO: Change the autogenerated stub
|
||||
}
|
||||
if (!is_object($this->_classMap[$name])) {
|
||||
$this->_classMap[$name] = Snowflake::createObject($this->_classMap[$name]);
|
||||
}
|
||||
return $this->_classMap[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReflectionClass $reflect
|
||||
* @return array
|
||||
*/
|
||||
protected function getPrivates(ReflectionClass $reflect)
|
||||
{
|
||||
$arrays = [];
|
||||
$properties = $reflect->getProperties(ReflectionMethod::IS_PRIVATE);
|
||||
foreach ($properties as $property) {
|
||||
$arrays[] = $property->getName();
|
||||
}
|
||||
return $arrays;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @return string[]
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function getAnnotation(string $class)
|
||||
{
|
||||
$reflect = Snowflake::getDi()->getReflect($class);
|
||||
|
||||
return $this->getPrivates($reflect);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/25 0025
|
||||
* Time: 18:38
|
||||
*/
|
||||
|
||||
namespace Snowflake;
|
||||
|
||||
|
||||
use Console\ConsoleProviders;
|
||||
use Database\DatabasesProviders;
|
||||
use Exception;
|
||||
use HttpServer\Server;
|
||||
use HttpServer\ServerProviders;
|
||||
use Snowflake\Abstracts\BaseApplication;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
|
||||
/**
|
||||
* Class Init
|
||||
*
|
||||
* @package Snowflake
|
||||
*
|
||||
* @property-read Config $config
|
||||
*/
|
||||
class Application extends BaseApplication
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $id = 'uniqueId';
|
||||
|
||||
|
||||
/**
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->import(ConsoleProviders::class);
|
||||
$this->import(DatabasesProviders::class);
|
||||
$this->import(ServerProviders::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $service
|
||||
* @return $this
|
||||
* @throws
|
||||
*/
|
||||
public function import(string $service)
|
||||
{
|
||||
if (!class_exists($service)) {
|
||||
throw new NotFindClassException($service);
|
||||
}
|
||||
$class = Snowflake::createObject($service);
|
||||
if (method_exists($class, 'onImport')) {
|
||||
$class->onImport($this);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
$manager = Snowflake::app()->server;
|
||||
$manager->start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $className
|
||||
* @param null $abstracts
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function make($className, $abstracts = null)
|
||||
{
|
||||
return make($className, $abstracts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/5/2 0002
|
||||
* Time: 14:51
|
||||
*/
|
||||
|
||||
namespace Snowflake\Cache;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Swoole\Coroutine\System;
|
||||
|
||||
/**
|
||||
* Class File
|
||||
* @package Snowflake\Snowflake\Cache
|
||||
*/
|
||||
class File extends Component implements ICache
|
||||
{
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init(); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $val
|
||||
*/
|
||||
public function set($key, $val)
|
||||
{
|
||||
if (is_array($val) || is_object($val)) {
|
||||
$val = serialize($val);
|
||||
}
|
||||
$tmpFile = $this->getCacheKey($key);
|
||||
if (!$this->exists($tmpFile)) {
|
||||
touch($tmpFile);
|
||||
}
|
||||
System::writeFile($tmpFile, $val, LOCK_EX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param array $hashKeys
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hMget($key, array $hashKeys)
|
||||
{
|
||||
$hash = $this->get($key);
|
||||
if (!is_array($hash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$nowHash = [];
|
||||
foreach ($hashKeys as $hashKey) {
|
||||
$nowHash[$hashKey] = $hash[$hashKey] ?? null;
|
||||
}
|
||||
return $nowHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param array $val
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hMset($key, array $val)
|
||||
{
|
||||
$hash = $this->get($key);
|
||||
if (!is_array($hash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$merge = array_merge($hash, $val);
|
||||
return $this->set($key, $merge);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKey
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hget($key, $hashKey)
|
||||
{
|
||||
$hash = $this->get($key);
|
||||
if (!is_array($hash)) {
|
||||
return false;
|
||||
}
|
||||
return $hash[$hashKey] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKey
|
||||
* @param $hashValue
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hset($key, $hashKey, $hashValue)
|
||||
{
|
||||
$hash = $this->get($key);
|
||||
if (!is_array($hash)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hash[$hashKey] = $hashValue;
|
||||
|
||||
return $this->set($key, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($key)
|
||||
{
|
||||
return file_exists($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
$tmpFile = $this->getCacheKey($key);
|
||||
if (!$this->exists($tmpFile)) {
|
||||
return NULL;
|
||||
}
|
||||
$content = file_get_contents($tmpFile);
|
||||
return unserialize($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return string
|
||||
* @throws
|
||||
*/
|
||||
private function getCacheKey($key)
|
||||
{
|
||||
return storage($key,'cache');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/11/8 0008
|
||||
* Time: 16:35
|
||||
*/
|
||||
|
||||
namespace Snowflake\Cache;
|
||||
|
||||
/**
|
||||
* Interface ICache
|
||||
* @package Snowflake\Snowflake\Cache
|
||||
*/
|
||||
interface ICache
|
||||
{
|
||||
/**
|
||||
* @param $key
|
||||
* @param $val
|
||||
* @return mixed
|
||||
*/
|
||||
public function set($key, $val);
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key);
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKeys
|
||||
* @return mixed
|
||||
*/
|
||||
public function hMget($key, array $hashKeys);
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param array $val
|
||||
* @return mixed
|
||||
*/
|
||||
public function hMset($key, array $val);
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKey
|
||||
* @return mixed
|
||||
*/
|
||||
public function hget($key, $hashKey);
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKey
|
||||
* @param $hashValue
|
||||
* @return mixed
|
||||
*/
|
||||
public function hset($key, $hashKey, $hashValue);
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($key);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace Snowflake\Cache;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Config;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Memcached
|
||||
* @package Yoc\cache
|
||||
*/
|
||||
class Memcached extends Component implements ICache
|
||||
{
|
||||
|
||||
/** @var \Memcached */
|
||||
private $_memcached;
|
||||
|
||||
public $host = '127.0.0.1';
|
||||
|
||||
public $port = 11211;
|
||||
|
||||
public $timeout = 60;
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$event = Snowflake::app()->event;
|
||||
$event->on(Event::RELEASE_ALL, [$this, 'destroy']);
|
||||
$event->on(Event::EVENT_AFTER_REQUEST, [$this, 'release']);
|
||||
|
||||
$id = Config::get('id', false, 'system');
|
||||
$this->_memcached = new \Memcached($id);
|
||||
$this->addServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Memcached
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnect()
|
||||
{
|
||||
return $this->_memcached;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws ConfigException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function addServer()
|
||||
{
|
||||
$array = [];
|
||||
$memcached = Config::get('cache.memcached');
|
||||
if (isset($memcached[0])) {
|
||||
foreach ($memcached as $value) {
|
||||
$array[] = [$value['host'], $value['port'], $value['weight']];
|
||||
}
|
||||
$isConnected = $this->_memcached->addServers($array);
|
||||
} else {
|
||||
$array[] = Config::get('cache.memcached.host', true);
|
||||
$array[] = Config::get('cache.memcached.port', true);
|
||||
$array[] = Config::get('cache.memcached.weight', true);
|
||||
$isConnected = $this->_memcached->addServer(...$array);
|
||||
}
|
||||
if (!$isConnected) {
|
||||
throw new Exception('Cache Memcache Host 127.0.0.1 Connect Fail.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $val
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function set($key, $val)
|
||||
{
|
||||
// TODO: Implement set() method.
|
||||
if (is_array($val) || is_object($val)) {
|
||||
$val = serialize($val);
|
||||
}
|
||||
|
||||
$this->_memcached->set($key, $val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
// TODO: Implement get() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param array $hashKeys
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hMget($key, array $hashKeys)
|
||||
{
|
||||
// TODO: Implement hMget() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param array $val
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hMset($key, array $val)
|
||||
{
|
||||
// TODO: Implement hMset() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKey
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hget($key, $hashKey)
|
||||
{
|
||||
// TODO: Implement hget() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $hashKey
|
||||
* @param $hashValue
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function hset($key, $hashKey, $hashValue)
|
||||
{
|
||||
// TODO: Implement hset() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return bool|void
|
||||
*/
|
||||
public function exists($key)
|
||||
{
|
||||
// TODO: Implement exists() method.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/27 0027
|
||||
* Time: 11:00
|
||||
*/
|
||||
|
||||
namespace Snowflake\Cache;
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Config;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Exception\RedisConnectException;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Coroutine;
|
||||
|
||||
/**
|
||||
* Class Redis
|
||||
* @package Snowflake\Snowflake\Cache
|
||||
* @see \Redis
|
||||
* @method append($key, $value): int
|
||||
* @method auth($password):
|
||||
* @method bgSave()
|
||||
* @method bgrewriteaof()
|
||||
* @method bitcount($key)
|
||||
* @method bitop($operation, $ret_key, $key, $other_keys = NULL)
|
||||
* @method bitpos($key, $bit, $start = NULL, $end = NULL)
|
||||
* @method blPop($key, $timeout_or_key, $extra_args = NULL)
|
||||
* @method brPop($key, $timeout_or_key, $extra_args = NULL)
|
||||
* @method brpoplpush($src, $dst, $timeout)
|
||||
* @method bzPopMax($key, $timeout_or_key, $extra_args = NULL)
|
||||
* @method bzPopMin($key, $timeout_or_key, $extra_args = NULL)
|
||||
* @method clearLastError()
|
||||
* @method client($cmd, $args = NULL)
|
||||
* @method close()
|
||||
* @method command($args = NULL)
|
||||
* @method config($cmd, $key, $value = NULL)
|
||||
* @method connect($host, $port = NULL, $timeout = NULL, $retry_interval = NULL)
|
||||
* @method dbSize()
|
||||
* @method debug($key)
|
||||
* @method decr($key)
|
||||
* @method decrBy($key, $value)
|
||||
* @method delete($key, $other_keys = NULL)
|
||||
* @method discard()
|
||||
* @method dump($key)
|
||||
* @method echo ($msg)
|
||||
* @method eval($script, $args = NULL, $num_keys = NULL)
|
||||
* @method evalsha($script_sha, $args = NULL, $num_keys = NULL)
|
||||
* @method exec()
|
||||
* @method exists($key, $other_keys = NULL)
|
||||
* @method expireAt($key, $timestamp)
|
||||
* @method flushAll($async = NULL)
|
||||
* @method flushDB($async = NULL)
|
||||
* @method geoadd($key, $lng, $lat, $member, $other_triples = NULL)
|
||||
* @method geodist($key, $src, $dst, $unit = NULL)
|
||||
* @method geohash($key, $member, $other_members = NULL)
|
||||
* @method geopos($key, $member, $other_members = NULL)
|
||||
* @method georadius($key, $lng, $lan, $radius, $unit, $opts = [])
|
||||
* @method georadius_ro($key, $lng, $lan, $radius, $unit, $opts = [])
|
||||
* @method georadiusbymember($key, $member, $radius, $unit, $opts = [])
|
||||
* @method georadiusbymember_ro($key, $member, $radius, $unit, $opts = [])
|
||||
* @method get($key)
|
||||
* @method getAuth()
|
||||
* @method getBit($key, $offset)
|
||||
* @method getDBNum()
|
||||
* @method getHost()
|
||||
* @method getKeys($pattern)
|
||||
* @method getLastError()
|
||||
* @method getMode()
|
||||
* @method getMultiple($keys)
|
||||
* @method getOption($option)
|
||||
* @method getPersistentID()
|
||||
* @method getPort()
|
||||
* @method getRange($key, $start, $end)
|
||||
* @method getReadTimeout()
|
||||
* @method getSet($key, $value)
|
||||
* @method getTimeout()
|
||||
* @method hDel($key, $member, $other_members = NULL)
|
||||
* @method hExists($key, $member)
|
||||
* @method hGet($key, $member)
|
||||
* @method hGetAll($key)
|
||||
* @method hIncrBy($key, $member, $value)
|
||||
* @method hIncrByFloat($key, $member, $value)
|
||||
* @method hKeys($key)
|
||||
* @method hLen($key)
|
||||
* @method hMget($key, $keys)
|
||||
* @method hMset($key, $pairs)
|
||||
* @method hSet($key, $member, $value)
|
||||
* @method hSetNx($key, $member, $value)
|
||||
* @method hStrLen($key, $member)
|
||||
* @method hVals($key)
|
||||
* @method hscan($str_key, $i_iterator, $str_pattern = NULL, $i_count = NULL)
|
||||
* @method incr($key)
|
||||
* @method incrBy($key, $value)
|
||||
* @method incrByFloat($key, $value)
|
||||
* @method info($option = NULL)
|
||||
* @method isConnected()
|
||||
* @method lGet($key, $index)
|
||||
* @method lGetRange($key, $start, $end)
|
||||
* @method lInsert($key, $position, $pivot, $value)
|
||||
* @method lPop($key)
|
||||
* @method lPush($key, $value)
|
||||
* @method lPushx($key, $value)
|
||||
* @method lRemove($key, $value, $count)
|
||||
* @method lSet($key, $index, $value)
|
||||
* @method lSize($key)
|
||||
* @method lastSave()
|
||||
* @method listTrim($key, $start, $stop)
|
||||
* @method migrate($host, $port, $key, $db, $timeout, $copy = NULL, $replace = NULL)
|
||||
* @method move($key, $dbindex)
|
||||
* @method mset($pairs)
|
||||
* @method msetnx($pairs)
|
||||
* @method multi($mode = NULL)
|
||||
* @method object($field, $key)
|
||||
* @method pconnect($host, $port = NULL, $timeout = NULL)
|
||||
* @method persist($key)
|
||||
* @method pexpire($key, $timestamp)
|
||||
* @method pexpireAt($key, $timestamp)
|
||||
* @method pfadd($key, $elements)
|
||||
* @method pfcount($key)
|
||||
* @method pfmerge($dstkey, $keys)
|
||||
* @method ping()
|
||||
* @method pipeline()
|
||||
* @method psetex($key, $expire, $value)
|
||||
* @method psubscribe($patterns, $callback)
|
||||
* @method pttl($key)
|
||||
* @method publish($channel, $message)
|
||||
* @method pubsub($cmd, $args = NULL)
|
||||
* @method punsubscribe($pattern, $other_patterns = NULL)
|
||||
* @method rPop($key)
|
||||
* @method rPush($key, $value)
|
||||
* @method rPushx($key, $value)
|
||||
* @method randomKey()
|
||||
* @method rawcommand($cmd, $args = NULL)
|
||||
* @method renameKey($key, $newkey)
|
||||
* @method renameNx($key, $newkey)
|
||||
* @method restore($ttl, $key, $value)
|
||||
* @method role()
|
||||
* @method rpoplpush($src, $dst)
|
||||
* @method sAdd($key, $value)
|
||||
* @method sAddArray($key, $options)
|
||||
* @method sContains($key, $value)
|
||||
* @method sDiff($key, $other_keys = NULL)
|
||||
* @method sDiffStore($dst, $key, $other_keys = NULL)
|
||||
* @method sInter($key, $other_keys = NULL)
|
||||
* @method sInterStore($dst, $key, $other_keys = NULL)
|
||||
* @method sMembers($key)
|
||||
* @method sMove($src, $dst, $value)
|
||||
* @method sPop($key)
|
||||
* @method sRandMember($key, $count = NULL)
|
||||
* @method sRemove($key, $member, $other_members = NULL)
|
||||
* @method sSize($key)
|
||||
* @method sUnion($key, $other_keys = NULL)
|
||||
* @method sUnionStore($dst, $key, $other_keys = NULL)
|
||||
* @method save()
|
||||
* @method scan($i_iterator, $str_pattern = NULL, $i_count = NULL)
|
||||
* @method script($cmd, $args = NULL)
|
||||
* @method select($dbindex)
|
||||
* @method set($key, $value, $opts = NULL)
|
||||
* @method setBit($key, $offset, $value)
|
||||
* @method setOption($option, $value)
|
||||
* @method setRange($key, $offset, $value)
|
||||
* @method setTimeout($key, $timeout)
|
||||
* @method setex($key, $expire, $value)
|
||||
* @method setnx($key, $value)
|
||||
* @method slaveof($host = NULL, $port = NULL)
|
||||
* @method slowlog($arg, $option = NULL)
|
||||
* @method sort($key, $options = [])
|
||||
* @method sortAsc($key, $pattern = NULL, $get = NULL, $start = NULL, $end = NULL, $getList = NULL)
|
||||
* @method sortAscAlpha($key, $pattern = NULL, $get = NULL, $start = NULL, $end = NULL, $getList = NULL)
|
||||
* @method sortDesc($key, $pattern = NULL, $get = NULL, $start = NULL, $end = NULL, $getList = NULL)
|
||||
* @method sortDescAlpha($key, $pattern = NULL, $get = NULL, $start = NULL, $end = NULL, $getList = NULL)
|
||||
* @method sscan($str_key, $i_iterator, $str_pattern = NULL, $i_count = NULL)
|
||||
* @method strlen($key)
|
||||
* @method subscribe($channels, $callback)
|
||||
* @method swapdb($srcdb, $dstdb)
|
||||
* @method time()
|
||||
* @method ttl($key)
|
||||
* @method type($key)
|
||||
* @method unlink($key, $other_keys = NULL)
|
||||
* @method unsubscribe($channel, $other_channels = NULL)
|
||||
* @method unwatch()
|
||||
* @method wait($numslaves, $timeout)
|
||||
* @method watch($key, $other_keys = NULL)
|
||||
* @method xack($str_key, $str_group, $arr_ids)
|
||||
* @method xadd($str_key, $str_id, $arr_fields, $i_maxlen = NULL, $boo_approximate = NULL)
|
||||
* @method xclaim($str_key, $str_group, $str_consumer, $i_min_idle, $arr_ids, $arr_opts = [])
|
||||
* @method xdel($str_key, $arr_ids)
|
||||
* @method xgroup($str_operation, $str_key = NULL, $str_arg1 = NULL, $str_arg2 = NULL, $str_arg3 = NULL)
|
||||
* @method xinfo($str_cmd, $str_key = NULL, $str_group = NULL)
|
||||
* @method xlen($key)
|
||||
* @method xpending($str_key, $str_group, $str_start = NULL, $str_end = NULL, $i_count = NULL, $str_consumer = NULL)
|
||||
* @method xrange($str_key, $str_start, $str_end, $i_count = NULL)
|
||||
* @method xread($arr_streams, $i_count = NULL, $i_block = NULL)
|
||||
* @method xreadgroup($str_group, $str_consumer, $arr_streams, $i_count = NULL, $i_block = NULL)
|
||||
* @method xrevrange($str_key, $str_start, $str_end, $i_count = NULL)
|
||||
* @method xtrim($str_key, $i_maxlen, $boo_approximate = NULL)
|
||||
* @method zAdd($key, $score, $value)
|
||||
* @method zCard($key)
|
||||
* @method zCount($key, $min, $max)
|
||||
* @method zDelete($key, $member, $other_members = NULL)
|
||||
* @method zDeleteRangeByRank($key, $start, $end)
|
||||
* @method zDeleteRangeByScore($key, $min, $max)
|
||||
* @method zIncrBy($key, $value, $member)
|
||||
* @method zInter($key, $keys, $weights = [], $aggregate = NULL)
|
||||
* @method zLexCount($key, $min, $max)
|
||||
* @method zRange($key, $start, $end, $scores = NULL)
|
||||
* @method zRangeByLex($key, $min, $max, $offset = NULL, $limit = NULL)
|
||||
* @method zRangeByScore($key, $start, $end, $options = [])
|
||||
* @method zRank($key, $member)
|
||||
* @method zRemRangeByLex($key, $min, $max)
|
||||
* @method zRevRange($key, $start, $end, $scores = NULL)
|
||||
* @method zRevRangeByLex($key, $min, $max, $offset = NULL, $limit = NULL)
|
||||
* @method zRevRangeByScore($key, $start, $end, $options = [])
|
||||
* @method zRevRank($key, $member)
|
||||
* @method zScore($key, $member)
|
||||
* @method zUnion($key, $keys, $weights = [], $aggregate = NULL)
|
||||
* @method zscan($str_key, $i_iterator, $str_pattern = NULL, $i_count = NULL)
|
||||
* @method zPopMax($key)
|
||||
* @method zPopMin($key)
|
||||
* @method del($key, $other_keys = NULL)
|
||||
* @method evaluate($script, $args = NULL, $num_keys = NULL)
|
||||
* @method evaluateSha($script_sha, $args = NULL, $num_keys = NULL)
|
||||
* @method expire($key, $timeout)
|
||||
* @method keys($pattern)
|
||||
* @method lLen($key)
|
||||
* @method lindex($key, $index)
|
||||
* @method lrange($key, $start, $end)
|
||||
* @method lrem($key, $value, $count)
|
||||
* @method ltrim($key, $start, $stop)
|
||||
* @method mget($keys)
|
||||
* @method open($host, $port = NULL, $timeout = NULL, $retry_interval = NULL)
|
||||
* @method popen($host, $port = NULL, $timeout = NULL)
|
||||
* @method rename($key, $newkey)
|
||||
* @method sGetMembers($key)
|
||||
* @method scard($key)
|
||||
* @method sendEcho($msg)
|
||||
* @method sismember($key, $value)
|
||||
* @method srem($key, $member, $other_members = NULL)
|
||||
* @method substr($key, $start, $end)
|
||||
* @method zRem($key, $member, $other_members = NULL)
|
||||
* @method zRemRangeByRank($key, $min, $max)
|
||||
* @method zRemRangeByScore($key, $min, $max)
|
||||
* @method zRemove($key, $member, $other_members = NULL)
|
||||
* @method zRemoveRangeByScore($key, $min, $max)
|
||||
* @method zReverseRange($key, $start, $end, $scores = NULL)
|
||||
* @method zSize($key)
|
||||
* @method zinterstore($key, $keys, $weights = [], $aggregate = NULL)
|
||||
* @method zunionstore($key, $keys, $weights = [], $aggregate = NULL)
|
||||
*/
|
||||
class Redis extends Component
|
||||
{
|
||||
public $host = '127.0.0.1';
|
||||
public $auth = 'xl.2005113426';
|
||||
public $port = 6973;
|
||||
public $databases = 0;
|
||||
public $timeout = -1;
|
||||
public $prefix = 'idd';
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$event = Snowflake::app()->event;
|
||||
$event->on(Event::RELEASE_ALL, [$this, 'destroy']);
|
||||
$event->on(Event::EVENT_AFTER_REQUEST, [$this, 'release']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return mixed
|
||||
* @throws
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
$data = $this->{$name}(...$arguments);
|
||||
} else {
|
||||
$data = $this->proxy()->{$name}(...$arguments);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放连接池
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function release()
|
||||
{
|
||||
$connections = Snowflake::app()->pool->redis;
|
||||
$connections->release($this->get_config(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁连接池
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
$connections = Snowflake::app()->pool->redis;
|
||||
$connections->destroy($this->get_config(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Redis
|
||||
* @throws Exception
|
||||
*/
|
||||
public function proxy()
|
||||
{
|
||||
$connections = Snowflake::app()->pool->redis;
|
||||
|
||||
$config = $this->get_config();
|
||||
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
|
||||
|
||||
$connections->initConnections('redis:' . $name, true);
|
||||
$connections->setLength(env('REDIS.POOL_LENGTH', 100));
|
||||
|
||||
$client = $connections->getConnection($config, true);
|
||||
if (!($client instanceof \Redis)) {
|
||||
throw new Exception('Redis connections more.');
|
||||
}
|
||||
return $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function get_config(): array
|
||||
{
|
||||
$config = Config::get('cache.redis', false, [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '6379',
|
||||
'prefix' => Config::get('id'),
|
||||
'auth' => '',
|
||||
'databases' => '0',
|
||||
'read_timeout' => -1,
|
||||
'conn_timeout' => -1,
|
||||
]);
|
||||
return [
|
||||
'host' => $config['host'],
|
||||
'port' => $config['port'],
|
||||
'auth' => $config['auth'],
|
||||
'timeout' => $config['conn_timeout'],
|
||||
'databases' => $config['databases'],
|
||||
'read_timeout' => $config['read_timeout'],
|
||||
'prefix' => $config['prefix'],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 14:57
|
||||
*/
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class ArrayAccess
|
||||
* @package Snowflake\Core
|
||||
*/
|
||||
class ArrayAccess
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function toArray($data)
|
||||
{
|
||||
if (!is_object($data) && !is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
if (is_object($data)) {
|
||||
$data = self::objToArray($data);
|
||||
}
|
||||
$tmp = [];
|
||||
if (!is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
foreach ($data as $key => $val) {
|
||||
if (is_array($val) || is_object($val)) {
|
||||
$tmp[$key] = self::toArray($val);
|
||||
} else {
|
||||
$tmp[$key] = $val;
|
||||
}
|
||||
}
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function objToArray($data)
|
||||
{
|
||||
if (!is_object($data)) {
|
||||
return $data;
|
||||
}
|
||||
if (method_exists($data, 'get')) {
|
||||
$data = $data->get();
|
||||
if (is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
if (method_exists($data, 'toArray')) {
|
||||
$data = $data->toArray();
|
||||
} else {
|
||||
$data = get_object_vars((object)$data);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $oldArray
|
||||
* @param array $newArray
|
||||
* @return array
|
||||
*/
|
||||
public static function merge(array $oldArray, array $newArray)
|
||||
{
|
||||
if (empty($oldArray)) {
|
||||
return $newArray;
|
||||
} else if (empty($newArray)) {
|
||||
return $oldArray;
|
||||
}
|
||||
foreach ($newArray as $item => $value) {
|
||||
if (!isset($oldArray[$item])) {
|
||||
$oldArray[$item] = $value;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$oldArray[$item] = self::merge($oldArray[$item], $value);
|
||||
} else {
|
||||
$oldArray[$item] = $value;
|
||||
}
|
||||
}
|
||||
return $oldArray;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: dell
|
||||
* Date: 2019/1/14 0014
|
||||
* Time: 13:50
|
||||
*/
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class DateFormat
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class DateFormat
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $time
|
||||
* @return bool|false|int|string
|
||||
*/
|
||||
private static function check($time)
|
||||
{
|
||||
if ($time === null) {
|
||||
$time = time();
|
||||
} else if (is_numeric($time)) {
|
||||
$length = strlen(floatval($time));
|
||||
if ($length != 10 && $length != 13) {
|
||||
return false;
|
||||
}
|
||||
} else if (is_string($time)) {
|
||||
$time = strtotime($time);
|
||||
}
|
||||
|
||||
if (date('Y-m-d', $time)) {
|
||||
return $time;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param null $time
|
||||
* @return bool|false|int
|
||||
*
|
||||
* 获取指定日期当周第一天的时间
|
||||
*/
|
||||
public static function getWeekCurrentDay($time = null)
|
||||
{
|
||||
if (!($time = static::check($time))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$time = strtotime('-' . (date('N') - 1) . 'days', $time);
|
||||
|
||||
return strtotime(date('Y-m-d'), $time);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param null $time
|
||||
* @return bool|false|int
|
||||
*
|
||||
* 获取指定日期当月第一天的时间
|
||||
*/
|
||||
public static function getMonthCurrentDay($time = null)
|
||||
{
|
||||
if (!($time = static::check($time))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strtotime(date('Y-m', $time) . '-01');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $time
|
||||
* @return bool|false|int|string
|
||||
* 指定的月份有几天
|
||||
*/
|
||||
public static function getMonthTotalDay($time)
|
||||
{
|
||||
if (!($time = static::check($time))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$time = date('t', $time);
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $startTime
|
||||
* @param null $endTime
|
||||
* @return string
|
||||
*/
|
||||
public static function mtime($startTime, $endTime = null)
|
||||
{
|
||||
if ($endTime === null) {
|
||||
$endTime = microtime(true);
|
||||
}
|
||||
return sprintf('%.7f', $endTime - $startTime);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Dtl
|
||||
* @package Snowflake\Core
|
||||
*/
|
||||
class Dtl extends Component
|
||||
{
|
||||
|
||||
protected $params;
|
||||
|
||||
|
||||
/**
|
||||
* Dtl constructor.
|
||||
* @param $params
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
parent::__construct([]);
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
if (!is_array($this->params)) {
|
||||
return ArrayAccess::toArray($this->params);
|
||||
}
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
$array = $this->toArray();
|
||||
if (!isset($array[$name])) {
|
||||
return null;
|
||||
}
|
||||
return $array[$name];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
|
||||
/**
|
||||
* Class Help
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Help
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
public static function toXml(array $data)
|
||||
{
|
||||
$xml = "<xml>";
|
||||
foreach ($data as $key => $val) {
|
||||
if (is_numeric($val)) {
|
||||
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
|
||||
} else {
|
||||
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
|
||||
}
|
||||
}
|
||||
$xml .= "</xml>";
|
||||
return $xml;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $xml
|
||||
* @return array|mixed
|
||||
*/
|
||||
public static function toArray($xml)
|
||||
{
|
||||
if (empty($xml)) {
|
||||
return [];
|
||||
} else if (is_array($xml)) {
|
||||
return $xml;
|
||||
}
|
||||
if (!Xml::isXml($xml)) {
|
||||
$xml = JSON::decode($xml);
|
||||
}
|
||||
return $xml;
|
||||
|
||||
/* $matchQuote = '/(<\?xml.*?\?>)?<([a-zA-Z_]+)>(<([a-zA-Z_]+)><!.*?><\/\4>)+<\/\2>/';*/
|
||||
// if (!preg_match($matchQuote, $xml)) {
|
||||
// return self::jsonToArray($xml);
|
||||
// }
|
||||
// try {
|
||||
// $data = @simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
|
||||
// if ($data !== false) {
|
||||
// $data = json_decode(json_encode($data), TRUE);
|
||||
// } else {
|
||||
// $data = $xml;
|
||||
// }
|
||||
// } catch (\Exception $exception) {
|
||||
// $data = $xml;
|
||||
// } finally {
|
||||
// return $data;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
public static function jsonToArray($xml)
|
||||
{
|
||||
$_xml = json_decode($xml, true);
|
||||
if (is_null($_xml)) {
|
||||
return $xml;
|
||||
}
|
||||
return $_xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $xml
|
||||
* @return mixed
|
||||
*/
|
||||
public static function xmlToArray($xml)
|
||||
{
|
||||
if (is_array($xml)) {
|
||||
return $xml;
|
||||
}
|
||||
if (($data = @simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)) !== false) {
|
||||
return json_decode(json_encode($data), TRUE);
|
||||
}
|
||||
if (!is_null($json = json_decode($xml, TRUE))) {
|
||||
return $json;
|
||||
}
|
||||
return $xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $parameter
|
||||
* @return array|false|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function toString($parameter)
|
||||
{
|
||||
if (!is_string($parameter)) {
|
||||
$parameter = ArrayAccess::toArray($parameter);
|
||||
if (is_array($parameter)) {
|
||||
$parameter = JSON::encode($parameter);
|
||||
}
|
||||
}
|
||||
return $parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $json
|
||||
* @return false|mixed|string
|
||||
*/
|
||||
public static function toJson($json)
|
||||
{
|
||||
if (is_object($json)) {
|
||||
$json = get_object_vars($json);
|
||||
}
|
||||
if (is_array($json)) {
|
||||
return json_encode($json, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
$matchQuote = '/(<\?xml.*?\?>)?<([a-zA-Z_]+)>(<([a-zA-Z_]+)><!.*?><\/\4>)+<\/\2>/';
|
||||
if (preg_match($matchQuote, $json)) {
|
||||
$json = self::xmlToArray($json);
|
||||
} else {
|
||||
$json = json_decode($json, true);
|
||||
}
|
||||
if (!is_array($json)) {
|
||||
$json = [];
|
||||
}
|
||||
return json_encode($json, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $length
|
||||
* @return string
|
||||
*
|
||||
* 随机字符串
|
||||
*/
|
||||
public static function random($length = 20)
|
||||
{
|
||||
$res = [];
|
||||
$str = 'abcdefghijklmnopqrstuvwxyz';
|
||||
$str .= strtoupper($str) . '1234567890';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$rand = substr($str, rand(0, strlen($str) - 2), 1);
|
||||
if (empty($rand)) {
|
||||
$rand = substr($str, strlen($str) - 3, 1);
|
||||
}
|
||||
array_push($res, $rand);
|
||||
}
|
||||
|
||||
return implode($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
* @param $key
|
||||
* @param $type
|
||||
* @return string
|
||||
*/
|
||||
public static function sign(array $array, $key, $type)
|
||||
{
|
||||
ksort($array, SORT_ASC);
|
||||
$string = [];
|
||||
foreach ($array as $hashKey => $val) {
|
||||
if (empty($val)) {
|
||||
continue;
|
||||
}
|
||||
$string[] = $hashKey . '=' . $val;
|
||||
}
|
||||
$string[] = 'key=' . $key;
|
||||
$string = implode('&', $string);
|
||||
if ($type == 'MD5') {
|
||||
return strtoupper(md5($string));
|
||||
} else {
|
||||
return hash('sha256', $string);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-20
|
||||
* Time: 01:04
|
||||
*/
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class JSON
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class JSON
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return false|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function encode($data)
|
||||
{
|
||||
if (empty($data)) {
|
||||
return $data;
|
||||
}
|
||||
if (is_array($data)) {
|
||||
return self::filter(ArrayAccess::toArray($data));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return mixed
|
||||
*/
|
||||
private static function filter($data)
|
||||
{
|
||||
array_walk_recursive($data, function (&$value, $key) {
|
||||
if (!is_numeric($value)) {
|
||||
return;
|
||||
}
|
||||
if (is_int(+$value)) {
|
||||
$value = +$value;
|
||||
}
|
||||
});
|
||||
return json_encode($data, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param bool $asArray
|
||||
* @return mixed
|
||||
*/
|
||||
public static function decode($data, $asArray = true)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
return json_decode($data, $asArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $code
|
||||
* @param string $message
|
||||
* @param array $data
|
||||
* @param int $count
|
||||
* @param array $exPageInfo
|
||||
* @return mixed
|
||||
* @throws
|
||||
*/
|
||||
public static function to($code, $message = '', $data = [], $count = 0, $exPageInfo = [])
|
||||
{
|
||||
$params['code'] = $code;
|
||||
if (!is_string($message)) {
|
||||
$params['param'] = $message;
|
||||
if (!empty($data)) {
|
||||
$params['exPageInfo'] = $data;
|
||||
}
|
||||
$params['message'] = 'System success.';
|
||||
} else {
|
||||
$params['message'] = $message;
|
||||
$params['param'] = $data;
|
||||
}
|
||||
if (!empty($exPageInfo)) {
|
||||
$params['exPageInfo'] = $exPageInfo;
|
||||
}
|
||||
$params['count'] = $count;
|
||||
if (is_numeric($data) || !is_numeric($count)) {
|
||||
$params['count'] = $data;
|
||||
$params['exPageInfo'] = $count;
|
||||
}
|
||||
if ((int)$params['count'] == -100) {
|
||||
$params['count'] = 1;
|
||||
}
|
||||
|
||||
ksort($params, SORT_ASC);
|
||||
|
||||
return static::encode($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $state
|
||||
* @param $body
|
||||
* @return false|int|string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function output($state, $body)
|
||||
{
|
||||
$params['state'] = $state;
|
||||
$params['body'] = ArrayAccess::toArray($body);
|
||||
|
||||
return static::encode($params);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class Reader
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Reader
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param $filepath
|
||||
* @param int $page
|
||||
* @param int $size
|
||||
* @return array and int
|
||||
*/
|
||||
public static function readerServerLogPagination($filepath, $page = 1, $size = 20)
|
||||
{
|
||||
$count = 0;
|
||||
$strings = [];
|
||||
$offset = ($page - 1) * $size;
|
||||
|
||||
if (!file_exists($filepath)) {
|
||||
return [0, []];
|
||||
}
|
||||
|
||||
//只读方式打开文件
|
||||
$fp = fopen($filepath, "r");
|
||||
|
||||
//开始循环读取$buffer_size
|
||||
while (!feof($fp)) {
|
||||
//读文件到缓冲区
|
||||
$buffer = fgets($fp);
|
||||
$count++;
|
||||
if ($count > $offset && count($strings) < $size) {
|
||||
$strings[] = [
|
||||
'id' => $count,
|
||||
'content' => $buffer
|
||||
];
|
||||
}
|
||||
}
|
||||
//关闭文件
|
||||
fclose($fp);
|
||||
unset($fp);
|
||||
|
||||
return ['total' => $count, 'list' => $strings];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filename
|
||||
* @param $start
|
||||
* @param $lines
|
||||
* @return mixed
|
||||
*/
|
||||
public static function read_backward_line($filename, $start, $lines)
|
||||
{
|
||||
$lines++;
|
||||
$offset = -1;
|
||||
$read = '';
|
||||
$fp = @fopen($filename, "r");
|
||||
|
||||
$tmpStart = 0;
|
||||
while ($lines && fseek($fp, $offset, SEEK_END) >= 0) {
|
||||
|
||||
$c = fgetc($fp);
|
||||
if ($c == "\n" || $c == "\r") {
|
||||
if (++$tmpStart >= $start)
|
||||
$lines--;
|
||||
}
|
||||
|
||||
|
||||
if ($tmpStart >= $start)
|
||||
$read .= $c;
|
||||
$offset--;
|
||||
}
|
||||
|
||||
$read = trim($read);
|
||||
|
||||
$contents = [];
|
||||
$read = array_reverse(explode("\n", strrev($read)));
|
||||
foreach ($read as $key => $value) {
|
||||
if (empty($value)) {
|
||||
unset($read[$key]);
|
||||
} else {
|
||||
$contents[] = ['content' => $value, 'id' => $key + $start];
|
||||
}
|
||||
}
|
||||
|
||||
$response['total'] = self::read_count_by_file($filename);
|
||||
$response['list'] = $contents;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filepath
|
||||
* @return int
|
||||
*/
|
||||
private static function read_count_by_file($filepath)
|
||||
{
|
||||
$count = 0;
|
||||
//只读方式打开文件
|
||||
$fp = fopen($filepath, "r");
|
||||
|
||||
//开始循环读取$buffer_size
|
||||
while (fgets($fp)) {
|
||||
$count++;
|
||||
}
|
||||
//关闭文件
|
||||
fclose($fp);
|
||||
unset($fp);
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filepath
|
||||
* @param int $page
|
||||
* @param int $size
|
||||
* @return array
|
||||
*/
|
||||
public static function folderPagination($filepath, $page = 1, $size = 20)
|
||||
{
|
||||
$count = 0;
|
||||
$strings = [];
|
||||
$offset = ($page - 1) * $size;
|
||||
|
||||
if (!is_dir($filepath)) {
|
||||
return [0, []];
|
||||
}
|
||||
|
||||
foreach (glob($filepath . '/*') as $key => $value) {
|
||||
$count++;
|
||||
if ($key < $offset || count($strings) >= $size) {
|
||||
continue;
|
||||
}
|
||||
$explode = explode(DIRECTORY_SEPARATOR, $value);
|
||||
|
||||
$addTime = fileatime($value);
|
||||
$changeTime = filectime($value);
|
||||
$modifyTime = filemtime($value);
|
||||
$strings[] = [
|
||||
'id' => $count,
|
||||
'path' => $value,
|
||||
'isDir' => (int)is_dir($value),
|
||||
'name' => end($explode),
|
||||
'atime' => [
|
||||
'format' => date('Y-m-d H:i:s', $addTime),
|
||||
'microtime' => $addTime
|
||||
],
|
||||
'ctime' => [
|
||||
'format' => date('Y-m-d H:i:s', $changeTime),
|
||||
'microtime' => $changeTime
|
||||
],
|
||||
'mtime' => [
|
||||
'format' => date('Y-m-d H:i:s', $modifyTime),
|
||||
'microtime' => $modifyTime
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
array_multisort($strings, array_column($strings, 'isDir'), SORT_DESC);
|
||||
|
||||
return ['total' => $count, 'list' => $strings];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class Str
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Str
|
||||
{
|
||||
|
||||
const STRING = 'abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
const NUMBER = '01234567890';
|
||||
|
||||
/**
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
* 获取随机字符串
|
||||
*/
|
||||
public static function rand(int $length = 20)
|
||||
{
|
||||
$string = '';
|
||||
if ($length < 1) $length = 20;
|
||||
$default = self::STRING . strtoupper(self::STRING) . self::NUMBER;
|
||||
$default = str_split($default);
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$string .= $default[array_rand($default)];
|
||||
}
|
||||
return (string)$string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $length
|
||||
*
|
||||
* @return int
|
||||
* 获取随机数字
|
||||
*/
|
||||
public static function random(int $length = 20)
|
||||
{
|
||||
$number = '';
|
||||
$default = str_split(self::NUMBER);
|
||||
if ($length < 1) $length = 1;
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$number .= $default[array_rand($default)];
|
||||
}
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $string
|
||||
* @param $sublen
|
||||
* @param bool $strip_tags
|
||||
* @param string $append
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function cut_str_utf8($string, $sublen, $strip_tags = true, $append = '...')
|
||||
{
|
||||
if ($strip_tags) {
|
||||
$string = strip_tags($string);
|
||||
}//去掉签标
|
||||
$pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
|
||||
preg_match_all($pa, $string, $t_string);
|
||||
$str = "";
|
||||
for ($i = 0; $i < count($t_string[0]); $i++) {
|
||||
$str .= $t_string[0][$i];
|
||||
//转为gbk,一个汉字长度为2
|
||||
if (strlen(@iconv('utf-8', 'gbk', $str)) >= $sublen) {
|
||||
if ($i != count($t_string[0]) - 1) $str .= $append;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @param null $callback
|
||||
* @return bool
|
||||
* 判断是否为json字符串
|
||||
*/
|
||||
public static function isJson($data, $callback = null)
|
||||
{
|
||||
$json = !is_null(json_decode($data)) && !is_numeric($data);
|
||||
if ($json && is_callable($callback, true)) {
|
||||
return call_user_func($callback, $data);
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @param null $callBack
|
||||
* @return bool
|
||||
* 判断是否序列化字符串
|
||||
*/
|
||||
public static function isSerialize($data, $callBack = null)
|
||||
{
|
||||
$false = !empty($data) && unserialize($data) !== false;
|
||||
if ($false && is_callable($callBack, true)) {
|
||||
return call_user_func($callBack, $data);
|
||||
}
|
||||
return $false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $string
|
||||
* @param int $length
|
||||
*
|
||||
* @param string $append
|
||||
* @return string
|
||||
*/
|
||||
public static function cut($string, int $length = 20, $append = '...')
|
||||
{
|
||||
if (empty($string)) {
|
||||
return '';
|
||||
}
|
||||
if ($length < 1) {
|
||||
$length = 1;
|
||||
}
|
||||
$array = str_split($string);
|
||||
if (count($array) <= $length) {
|
||||
return implode('', $array);
|
||||
}
|
||||
$string = implode('', array_slice($array, 0, $length));
|
||||
if (!empty($append)) {
|
||||
$string .= $append;
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $str
|
||||
* @param int $number
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encrypt($str, $number = 10, $key = 'xshucai.com')
|
||||
{
|
||||
$res = [];
|
||||
$add = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
$len = strlen($key) < 0 ? 1 : strlen($key) + 5 > strlen($add) ? strlen($add) - 5 : strlen($key);
|
||||
if ($number < 1) $number = 10;
|
||||
$array = str_split($str);
|
||||
asort($array);
|
||||
$str = implode('', $array);
|
||||
for ($i = 0; $i < $number; $i++) {
|
||||
$_tmp = md5($key) . md5($str) . mb_substr($add, $len, $len + 5, 'utf-8');
|
||||
$res[] = md5($_tmp);
|
||||
}
|
||||
sort($res, SORT_STRING);
|
||||
return hash('sha384', implode('', $res));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @param $type
|
||||
* @return string
|
||||
*/
|
||||
public static function filename($file, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'image/png':
|
||||
return md5_file($file) . '.png';
|
||||
case 'image/jpeg':
|
||||
case 'image/jpg':
|
||||
return md5_file($file) . '.jpg';
|
||||
case 'image/gif':
|
||||
return md5_file($file) . '.gif';
|
||||
break;
|
||||
}
|
||||
return md5_file($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $endTime
|
||||
* @param int|null $startTime
|
||||
* @return array
|
||||
* 剩余天,带分秒
|
||||
*/
|
||||
public static function timeout($endTime, int $startTime = null)
|
||||
{
|
||||
$endTime = $endTime - (!empty($startTime) ? $startTime : time());
|
||||
|
||||
$day = intval($endTime / (3600 * 24));
|
||||
|
||||
$hours = intval(($endTime - ($day * (3600 * 24))) / 3600);
|
||||
|
||||
$minute = intval(($endTime - ($day * (3600 * 24) + $hours * 3600)) / 60);
|
||||
|
||||
$scrod = intval(($endTime - ($day * (3600 * 24) + $hours * 3600 + $minute * 60)));
|
||||
|
||||
return [$day, $hours, $minute, $scrod];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return false|int
|
||||
*/
|
||||
public static function get_sy_time()
|
||||
{
|
||||
$time = strtotime('+1days', strtotime(date('Y-m-d')));
|
||||
|
||||
return $time - time();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function encode(string $string)
|
||||
{
|
||||
return addslashes($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return string|string[]|null
|
||||
* 清除标点符号
|
||||
*/
|
||||
public static function clear(string $string)
|
||||
{
|
||||
$char = '。、!?:;﹑•"…‘’“”〝〞∕¦‖— 〈〉﹞﹝「」‹›〖〗】【»«』『〕〔》《﹐¸﹕︰﹔!¡?¿﹖﹌﹏﹋'´ˊˋ―﹫︳︴¯_ ̄﹢﹦﹤‐˜﹟﹩﹠﹪﹡﹨﹍﹉﹎﹊ˇ︵︶︷︸︹︿﹀︺︽︾ˉ﹁﹂﹃﹄︻︼()';
|
||||
return preg_replace(array("/[[:punct:]]/i", '/[' . $char . ']/u', '/[ ]{2,}/'), '', $string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $user
|
||||
* @param array $param
|
||||
* @param int $requestTime
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function token($user, $param = [], $requestTime = NULL)
|
||||
{
|
||||
$str = '';
|
||||
if (!$requestTime) {
|
||||
$requestTime = microtime(true);
|
||||
}
|
||||
$_user = str_split(md5($user . md5($user)));
|
||||
ksort($_user);
|
||||
foreach ($_user as $key => $val) {
|
||||
$str .= md5(sha1($key . $val . 'www.xshucai.com'));
|
||||
}
|
||||
if (is_array($param)) {
|
||||
foreach ($param as $key => $val) {
|
||||
$str .= md5($str . sha1($key . md5($val)));
|
||||
}
|
||||
}
|
||||
$str .= sha1(base64_encode($requestTime));
|
||||
|
||||
$md5 = md5($str . $user);
|
||||
|
||||
return preg_replace('/(\w{10})(\w{3})(\w{4})(\w{9})(\w{6})/', '$1-$2-$3-$4-$5', $md5);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-20
|
||||
* Time: 01:03
|
||||
*/
|
||||
|
||||
namespace Snowflake\Core;
|
||||
|
||||
/**
|
||||
* Class Xml
|
||||
* @package Snowflake\Snowflake\Core
|
||||
*/
|
||||
class Xml
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param bool $asArray
|
||||
* @return array|object
|
||||
*/
|
||||
public static function toArray($data, $asArray = true)
|
||||
{
|
||||
$data = simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
|
||||
if ($asArray) {
|
||||
return json_decode(json_encode($data), TRUE);
|
||||
}
|
||||
|
||||
return json_decode(json_encode($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $str
|
||||
* @return bool
|
||||
*/
|
||||
public static function isXml(&$str)
|
||||
{
|
||||
$xml_parser = xml_parser_create();
|
||||
if (!xml_parse($xml_parser, $str, true)) {
|
||||
xml_parser_free($xml_parser);
|
||||
return false;
|
||||
} else {
|
||||
$str = self::toArray($str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/24 0024
|
||||
* Time: 17:27
|
||||
*/
|
||||
|
||||
namespace Snowflake\Di;
|
||||
|
||||
use ReflectionClass;
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use ReflectionException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
|
||||
/**
|
||||
* Class Container
|
||||
* @package Snowflake\Di
|
||||
*/
|
||||
class Container extends BaseObject
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* instance class by className
|
||||
*/
|
||||
private $_singletons = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* class new instance construct parameter
|
||||
*/
|
||||
private $_constructs = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* implements \ReflectClass
|
||||
*/
|
||||
private $_reflection = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* The construct parameter
|
||||
*/
|
||||
private $_param = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @param array $constrict
|
||||
* @param array $config
|
||||
*
|
||||
* @return mixed
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function get($class, $constrict = [], $config = [])
|
||||
{
|
||||
if (isset($this->_singletons[$class])) {
|
||||
return $this->_singletons[$class];
|
||||
} else if (!isset($this->_constructs[$class])) {
|
||||
return $this->resolve($class, $constrict, $config);
|
||||
}
|
||||
$definition = $this->_constructs[$class];
|
||||
if (is_callable($definition, TRUE)) {
|
||||
return call_user_func($definition, $this, $constrict, $config);
|
||||
} else if (is_array($definition)) {
|
||||
$object = $this->resolveDefinition($definition, $class, $config, $constrict);
|
||||
} else if (is_object($definition)) {
|
||||
return $this->_singletons[$class] = $definition;
|
||||
} else {
|
||||
throw new NotFindClassException($class);
|
||||
}
|
||||
return $this->_singletons[$class] = $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $definition
|
||||
* @param $class
|
||||
* @param $config
|
||||
* @param $constrict
|
||||
* @return mixed
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function resolveDefinition($definition, $class, $config, $constrict)
|
||||
{
|
||||
if (!isset($definition['class'])) {
|
||||
throw new NotFindClassException($class);
|
||||
}
|
||||
$_className = $definition['class'];
|
||||
unset($definition['class']);
|
||||
|
||||
$config = array_merge($definition, $config);
|
||||
$definition = $this->mergeParam($class, $constrict);
|
||||
|
||||
if ($_className === $class) {
|
||||
$object = $this->resolve($class, $definition, $config);
|
||||
} else {
|
||||
$object = $this->get($class, $definition, $config);
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @param $constrict
|
||||
* @param $config
|
||||
*
|
||||
* @return mixed
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function resolve($class, $constrict, $config)
|
||||
{
|
||||
/**
|
||||
* @var ReflectionClass $reflect
|
||||
* @var array $dependencies
|
||||
*/
|
||||
list($reflect, $dependencies) = $this->resolveDependencies($class);
|
||||
foreach ($constrict as $index => $param) {
|
||||
$dependencies[$index] = $param;
|
||||
}
|
||||
if (!$reflect->isInstantiable()) {
|
||||
throw new NotFindClassException($reflect->getName());
|
||||
}
|
||||
if (empty($config)) {
|
||||
return $reflect->newInstanceArgs($dependencies ?? []);
|
||||
}
|
||||
|
||||
if (!empty($dependencies) && $reflect->implementsInterface('Snowflake\Abstracts\Configure')) {
|
||||
$dependencies[count($dependencies) - 1] = $config;
|
||||
return $reflect->newInstanceArgs($dependencies);
|
||||
}
|
||||
if (!empty($config)) {
|
||||
$this->_param[$class] = $config;
|
||||
}
|
||||
$object = $reflect->newInstanceArgs($dependencies ?? []);
|
||||
foreach ($config as $key => $val) {
|
||||
$object->{$key} = $val;
|
||||
}
|
||||
if (method_exists($object, 'afterInit')) {
|
||||
call_user_func([$object, 'afterInit']);
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
*
|
||||
* @return array
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function resolveDependencies($class)
|
||||
{
|
||||
$dependencies = [];
|
||||
if (isset($this->_reflection[$class])) {
|
||||
$reflection = $this->_reflection[$class];
|
||||
} else {
|
||||
$reflection = new ReflectionClass($class);
|
||||
$this->_reflection[$class] = $reflection;
|
||||
}
|
||||
$constructs = $reflection->getConstructor();
|
||||
if (empty($constructs) || !is_array($constructs)) {
|
||||
return [$reflection, []];
|
||||
}
|
||||
foreach ($constructs->getParameters() as $key => $param) {
|
||||
if (version_compare(PHP_VERSION, '5.6.0', '>=') && $param->isVariadic()) {
|
||||
break;
|
||||
} else if ($param->isDefaultValueAvailable()) {
|
||||
$dependencies[] = $param->getDefaultValue();
|
||||
} else {
|
||||
$c = $param->getClass();
|
||||
$dependencies[] = $c === NULL ? NULL : $c->getName();
|
||||
}
|
||||
}
|
||||
$this->_constructs[$class] = $dependencies;
|
||||
return [$reflection, $dependencies];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @return mixed
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function getReflect($class): ReflectionClass
|
||||
{
|
||||
if (!isset($this->_reflection[$class])) {
|
||||
$this->resolveDependencies($class);
|
||||
}
|
||||
return $this->_reflection[$class];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
*/
|
||||
public function unset($class)
|
||||
{
|
||||
if (is_array($class) && isset($class['class'])) {
|
||||
$class = $class['class'];
|
||||
} else if (is_object($class)) {
|
||||
$class = get_class($class);
|
||||
}
|
||||
unset(
|
||||
$this->_reflection[$class], $this->_singletons[$class],
|
||||
$this->_param[$class], $this->_constructs[$class]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
$this->_reflection = [];
|
||||
$this->_singletons = [];
|
||||
$this->_param = [];
|
||||
$this->_constructs = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @param $newParam
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function mergeParam($class, $newParam)
|
||||
{
|
||||
if (empty($this->_param[$class])) {
|
||||
return $newParam;
|
||||
} else if (empty($newParam)) {
|
||||
return $this->_param[$class];
|
||||
}
|
||||
$old = $this->_param[$class];
|
||||
foreach ($newParam as $key => $val) {
|
||||
$old[$key] = $val;
|
||||
}
|
||||
return $old;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/25 0025
|
||||
* Time: 18:29
|
||||
*/
|
||||
|
||||
namespace Snowflake\Di;
|
||||
|
||||
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Service
|
||||
* @package Snowflake\Snowflake\Di
|
||||
*/
|
||||
class Service extends Component
|
||||
{
|
||||
|
||||
private $_components = [];
|
||||
|
||||
|
||||
private $_definition = [];
|
||||
|
||||
|
||||
protected $_alias = [];
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
* @return mixed
|
||||
* @throws
|
||||
*/
|
||||
public function get($id)
|
||||
{
|
||||
if (isset($this->_components[$id])) {
|
||||
return $this->_components[$id];
|
||||
}
|
||||
if (isset($this->_definition[$id])) {
|
||||
$object = $this->_definition[$id];
|
||||
if (!is_object($object)) {
|
||||
$object = Snowflake::createObject($object);
|
||||
}
|
||||
} else if (!isset($this->_alias[$id])) {
|
||||
throw new ComponentException("Unknown component ID: $id");
|
||||
} else {
|
||||
$id = $this->_alias[$id];
|
||||
|
||||
$object = Snowflake::createObject($id);
|
||||
}
|
||||
return $this->_components[$id] = $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $alias
|
||||
*/
|
||||
public function setAlias(string $className, string $alias)
|
||||
{
|
||||
$this->_alias[$className] = $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $definition
|
||||
*
|
||||
* @return callable|mixed|void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function set($id, $definition)
|
||||
{
|
||||
if ($definition === NULL) {
|
||||
return $this->remove($id);
|
||||
}
|
||||
unset($this->_components[$id]);
|
||||
if (is_object($definition) || is_callable($definition, TRUE)) {
|
||||
return $this->_definition[$id] = $definition;
|
||||
} else if (!is_array($definition)) {
|
||||
throw new ComponentException("Unexpected configuration type for the \"$id\" component: " . gettype($definition));
|
||||
}
|
||||
if (!isset($definition['class'])) {
|
||||
throw new ComponentException("The configuration for the \"$id\" component must contain a \"class\" element.");
|
||||
} else {
|
||||
$this->_definition[$id] = $definition;
|
||||
}
|
||||
return $this->_components[$id] = Snowflake::createObject($definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return bool
|
||||
*/
|
||||
public function has($id)
|
||||
{
|
||||
return isset($this->_definition[$id]) || isset($this->_components[$id]) || isset($this->_alias[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setComponents(array $data)
|
||||
{
|
||||
foreach ($data as $key => $val) {
|
||||
$this->set($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if ($this->has($name)) {
|
||||
return $this->get($name);
|
||||
}
|
||||
|
||||
return parent::__get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
unset($this->_components[$id]);
|
||||
unset($this->_definition[$id]);
|
||||
if (isset($this->_alias[$id])) {
|
||||
unset($this->_components[$this->_alias[$id]]);
|
||||
unset($this->_definition[$this->_alias[$id]]);
|
||||
unset($this->_alias[$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/26 0026
|
||||
* Time: 10:00
|
||||
*/
|
||||
|
||||
namespace Snowflake\Error;
|
||||
|
||||
use Exception;
|
||||
use HttpServer\IInterface\IFormatter;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\JSON;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class ErrorHandler
|
||||
*
|
||||
* @package Snowflake\Snowflake\Base
|
||||
* @property-read $asError
|
||||
*/
|
||||
class ErrorHandler extends Component implements ErrorInterface
|
||||
{
|
||||
|
||||
/** @var IFormatter $message */
|
||||
private $message = NULL;
|
||||
|
||||
public $action;
|
||||
|
||||
public $category = 'app';
|
||||
|
||||
/**
|
||||
* 错误处理注册
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
ini_set('display_errors', 0);
|
||||
set_exception_handler([$this, 'exceptionHandler']);
|
||||
if (defined('HHVM_VERSION')) {
|
||||
set_error_handler([$this, 'errorHandler']);
|
||||
} else {
|
||||
set_error_handler([$this, 'errorHandler']);
|
||||
}
|
||||
register_shutdown_function([$this, 'shutdown']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function shutdown()
|
||||
{
|
||||
$lastError = error_get_last();
|
||||
if ($lastError['type'] !== E_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->category = 'shutdown';
|
||||
|
||||
$messages = explode(PHP_EOL, $lastError['message']);
|
||||
|
||||
$message = array_shift($messages);
|
||||
|
||||
$this->sendError($message, $lastError['file'], $lastError['line']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Exception $exception
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exceptionHandler($exception)
|
||||
{
|
||||
$this->category = 'exception';
|
||||
|
||||
$event = Snowflake::app()->event;
|
||||
$event->trigger(Event::RELEASE_ALL);
|
||||
|
||||
$this->sendError($exception->getMessage(), $exception->getFile(), $exception->getLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*
|
||||
* 以异常形式抛出错误,防止执行后续程序
|
||||
*/
|
||||
public function errorHandler()
|
||||
{
|
||||
$error = func_get_args();
|
||||
if (strpos($error[2], 'vendor/Reboot.php') !== FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$path = ['file' => $error[2], 'line' => $error[3]];
|
||||
|
||||
if ($error[0] === 0) {
|
||||
$error[0] = 500;
|
||||
}
|
||||
|
||||
$data = JSON::to(500, 'Error : ' . $error[1], $path);
|
||||
|
||||
Snowflake::app()->getLogger()->error($data, 'error');
|
||||
|
||||
$event = Snowflake::app()->event;
|
||||
$event->trigger(Event::RELEASE_ALL);
|
||||
|
||||
throw new \ErrorException($error[1], $error[0], 1, $error[2], $error[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param $file
|
||||
* @param $line
|
||||
* @param int $code
|
||||
* @return false|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendError($message, $file, $line, $code = 500)
|
||||
{
|
||||
$path = ['file' => $file, 'line' => $line];
|
||||
|
||||
$data = JSON::to($code, $this->category . ': ' . $message, $path);
|
||||
|
||||
Snowflake::app()->getLogger()->trance($data, $this->category);
|
||||
|
||||
return response()->send($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getErrorMessage()
|
||||
{
|
||||
$message = $this->message;
|
||||
$this->message = NULL;
|
||||
return $message->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function getAsError()
|
||||
{
|
||||
return $this->message !== NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param $category
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function writer($message, $category = 'app')
|
||||
{
|
||||
Snowflake::app()->getLogger()->debug($message, $category);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-20
|
||||
* Time: 10:25
|
||||
*/
|
||||
|
||||
namespace Snowflake\Error;
|
||||
|
||||
/**
|
||||
* Interface ErrorInterface
|
||||
* @package Snowflake\Snowflake\Error
|
||||
*/
|
||||
interface ErrorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param $file
|
||||
* @param $line
|
||||
* @param int $code
|
||||
* @return mixed
|
||||
*/
|
||||
public function sendError($message, $file, $line, $code = 500);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-22
|
||||
* Time: 14:36
|
||||
*/
|
||||
|
||||
namespace Snowflake\Error;
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\JSON;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Process;
|
||||
|
||||
/**
|
||||
* Class Logger
|
||||
* @package Snowflake\Snowflake\Error
|
||||
*/
|
||||
class Logger extends Component
|
||||
{
|
||||
|
||||
private $logs = [];
|
||||
|
||||
public $worker_id;
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $category
|
||||
* @param null $_
|
||||
* @throws Exception
|
||||
*/
|
||||
public function debug($message, $category = 'app', $_ = null)
|
||||
{
|
||||
parent::debug($message);
|
||||
$this->writer($message, $category);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $category
|
||||
* @throws Exception
|
||||
*/
|
||||
public function trance($message, $category = 'app')
|
||||
{
|
||||
$this->writer($message, $category);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $category
|
||||
* @param null $_
|
||||
* @throws Exception
|
||||
*/
|
||||
public function error($message, $category = 'error', $_ = null)
|
||||
{
|
||||
parent::error($message);
|
||||
$this->writer($message, $category);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $category
|
||||
* @param null $_
|
||||
* @throws Exception
|
||||
*/
|
||||
public function success($message, $category = 'app', $_ = null)
|
||||
{
|
||||
parent::success($message);
|
||||
$this->writer($message, $category);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $category
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function writer($message, $category = 'app')
|
||||
{
|
||||
if ($message instanceof \Throwable) {
|
||||
$message = $message->getMessage();
|
||||
} else {
|
||||
if (is_array($message) || is_object($message)) {
|
||||
$message = $this->arrayFormat($message);
|
||||
}
|
||||
}
|
||||
if (is_array($message)) {
|
||||
$message = $this->arrayFormat($message);
|
||||
}
|
||||
if (!empty($message)) {
|
||||
if (!is_array($this->logs)) {
|
||||
$this->logs = [];
|
||||
}
|
||||
$this->logs[] = [$category, $message];
|
||||
}
|
||||
return $message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param $category
|
||||
* @throws Exception
|
||||
*/
|
||||
public function print_r($message, $category = '')
|
||||
{
|
||||
/** @var Process $logger */
|
||||
$logger = Snowflake::app()->logger;
|
||||
$logger->write(JSON::encode([$message, $category]));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $application
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastError($application = 'app')
|
||||
{
|
||||
$_tmp = [];
|
||||
foreach ($this->logs as $key => $val) {
|
||||
if ($val[0] != $application) {
|
||||
continue;
|
||||
}
|
||||
$_tmp[] = $val[1];
|
||||
}
|
||||
if (empty($_tmp)) {
|
||||
return 'Unknown error.';
|
||||
}
|
||||
return end($_tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $messages
|
||||
* @param string $category
|
||||
* @throws Exception
|
||||
*/
|
||||
public function write(string $messages, $category = 'app')
|
||||
{
|
||||
if (empty($messages)) {
|
||||
return;
|
||||
}
|
||||
$fileName = 'server-' . date('Y-m-d') . '.log';
|
||||
$dirName = 'log/' . (empty($category) ? 'app' : $category);
|
||||
$logFile = '[' . date('Y-m-d H:i:s') . ']:' . PHP_EOL . $messages . PHP_EOL;
|
||||
Snowflake::writeFile(storage($fileName, $dirName), $logFile, FILE_APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $logFile
|
||||
* @return false|string
|
||||
*/
|
||||
private function getSource($logFile)
|
||||
{
|
||||
if (!file_exists($logFile)) {
|
||||
shell_exec('echo 3 > /proc/sys/vm/drop_caches');
|
||||
touch($logFile);
|
||||
}
|
||||
if (is_writeable($logFile)) {
|
||||
$logFile = realpath($logFile);
|
||||
}
|
||||
return $logFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 写入日志
|
||||
*/
|
||||
public function insert()
|
||||
{
|
||||
if (empty($this->logs)) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->logs as $log) {
|
||||
[$category, $message] = $log;
|
||||
$this->write($message, $category);
|
||||
}
|
||||
$this->logs = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
return $this->logs = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
private function arrayFormat($data)
|
||||
{
|
||||
if (is_string($data)) {
|
||||
return $data;
|
||||
}
|
||||
if ($data instanceof Exception) {
|
||||
$data = $this->getException($data);
|
||||
} else if (is_object($data)) {
|
||||
$data = get_object_vars($data);
|
||||
}
|
||||
|
||||
$_tmp = [];
|
||||
foreach ($data as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$_tmp[] = $this->arrayFormat($val);
|
||||
} else {
|
||||
$_tmp[] = (is_string($key) ? $key . ' : ' : '') . $val;
|
||||
}
|
||||
}
|
||||
return implode(PHP_EOL, $_tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Exception $exception
|
||||
* @return array
|
||||
*/
|
||||
private function getException($exception)
|
||||
{
|
||||
$_tmp = [$exception->getMessage()];
|
||||
$_tmp[] = $exception->getFile() . ' on line ' . $exception->getLine();
|
||||
$_tmp[] = $exception->getTrace();
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Snowflake\Core\ArrayAccess;
|
||||
|
||||
/**
|
||||
* Class Event
|
||||
* @package Snowflake
|
||||
*/
|
||||
class Event extends BaseObject
|
||||
{
|
||||
|
||||
public $isVide = true;
|
||||
|
||||
private $_events = [];
|
||||
|
||||
const EVENT_ERROR = 'WORKER:ERROR';
|
||||
const EVENT_STOP = 'WORKER:STOP';
|
||||
const EVENT_EXIT = 'WORKER:EXIT';
|
||||
|
||||
const PIPE_MESSAGE = 'SERVER:PIPE:MESSAGE';
|
||||
|
||||
const EVENT_AFTER_REQUEST = 'SERVER:REQUEST:AFTER:START';
|
||||
const EVENT_BEFORE_REQUEST = 'SERVER:REQUEST:BEFORE:START';
|
||||
const RECEIVE_CONNECTION = 'SERVER:RECEIVE:CONNECTION';
|
||||
|
||||
|
||||
const PROCESS_WORKER_STOP = 'SERVER:PROCESS:WORKER:STOP';
|
||||
|
||||
const RELEASE_ALL = 'SERVER:RELEASE:ALL';
|
||||
|
||||
const SERVER_AFTER_RELOAD = 'SERVER:AFTER:RELOAD';
|
||||
const SERVER_BEFORE_RELOAD = 'SERVER:BEFORE:RELOAD';
|
||||
|
||||
const SERVER_EVENT_START = 'SERVER:EVENT:START';
|
||||
const SERVER_MANAGER_START = 'SERVER:EVENT:MANAGER:START';
|
||||
const SERVER_MANAGER_STOP = 'SERVER:EVENT:MANAGER:START';
|
||||
const SERVER_WORKER_STOP = 'SERVER:EVENT:WORKER:STOP';
|
||||
const SERVER_WORKER_START = 'SERVER:EVENT:WORKER:START';
|
||||
const SERVER_WORKER_EXIT = 'SERVER:EVENT:WORKER:EXIT';
|
||||
const SERVER_WORKER_ERROR = 'SERVER:EVENT:WORKER:ERROR';
|
||||
const SERVER_SHUTDOWN = 'SERVER:EVENT:SHUTDOWN';
|
||||
|
||||
const SERVER_HANDSHAKE = 'on handshake';
|
||||
const SERVER_MESSAGE = 'on message';
|
||||
const SERVER_CLOSE = 'on close';
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $callback
|
||||
* @param array $parameter
|
||||
* @param bool $isAppend
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function on($name, $callback, $parameter = [], $isAppend = true)
|
||||
{
|
||||
if (!isset($this->_events[$name])) {
|
||||
$this->_events[$name] = [];
|
||||
}
|
||||
if ($callback instanceof \Closure) {
|
||||
$callback = \Closure::bind($callback, Snowflake::app());
|
||||
} else if (is_array($callback) && is_string($callback[0])) {
|
||||
if (!class_exists($callback[0])) {
|
||||
throw new \Exception('Undefined callback class.');
|
||||
}
|
||||
$callback[0] = Snowflake::createObject($callback[0]);
|
||||
}
|
||||
if (!empty($this->_events[$name]) && $isAppend === true) {
|
||||
array_unshift($this->_events[$name], [$callback, $parameter]);
|
||||
} else {
|
||||
$this->_events[$name][] = [$callback, $parameter];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $callback
|
||||
*/
|
||||
public function of($name, $callback)
|
||||
{
|
||||
if (!isset($this->_events[$name])) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->_events[$name] as $index => $event) {
|
||||
[$handler, $parameter] = $event;
|
||||
if ($handler !== $callback) {
|
||||
continue;
|
||||
}
|
||||
unset($this->_events[$name][$index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return bool
|
||||
*/
|
||||
public function offName($name)
|
||||
{
|
||||
if (!$this->exists($name)) {
|
||||
return true;
|
||||
}
|
||||
unset($this->_events[$name]);
|
||||
return $this->exists($name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($name, $callback = null)
|
||||
{
|
||||
if (!isset($this->_events[$name])) {
|
||||
return false;
|
||||
}
|
||||
if ($callback === null) {
|
||||
return true;
|
||||
}
|
||||
foreach ($this->_events[$name] as $event) {
|
||||
[$handler, $parameter] = $event;
|
||||
if ($handler === $callback) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $handler
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function get($name, $handler)
|
||||
{
|
||||
if (!$this->exists($name)) {
|
||||
return null;
|
||||
}
|
||||
foreach ($this->_events[$name] as $event) {
|
||||
[$callback, $parameter] = $event;
|
||||
if ($callback === $handler) {
|
||||
return $event;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function clean()
|
||||
{
|
||||
$this->_events = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $handler
|
||||
* @param null $parameter
|
||||
* @param false $is_remove
|
||||
* @return bool|mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function trigger($name, $parameter = null, $handler = null, $is_remove = false)
|
||||
{
|
||||
if (!$this->exists($name)) {
|
||||
return false;
|
||||
}
|
||||
if (!empty($handler) && $this->exists($name, $handler)) {
|
||||
[$handler, $defaultParameter] = $this->get($name, $handler);
|
||||
if (!empty($parameter)) {
|
||||
$defaultParameter = ArrayAccess::merge($defaultParameter, $parameter);
|
||||
}
|
||||
if (!is_array($defaultParameter)) {
|
||||
$defaultParameter = [$defaultParameter];
|
||||
}
|
||||
$result = call_user_func($handler, ...$defaultParameter);
|
||||
if ($is_remove) {
|
||||
$this->of($name, $handler);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
foreach ($this->_events[$name] as $event) {
|
||||
[$handler, $defaultParameter] = $event;
|
||||
try {
|
||||
if (!empty($parameter)) {
|
||||
$defaultParameter = ArrayAccess::merge($defaultParameter, $parameter);
|
||||
}
|
||||
if (!is_array($defaultParameter)) {
|
||||
$defaultParameter = [$defaultParameter];
|
||||
}
|
||||
call_user_func($handler, ...$defaultParameter);
|
||||
} catch (\Throwable $exception) {
|
||||
$this->error($exception->getMessage());
|
||||
}
|
||||
}
|
||||
if ($is_remove) {
|
||||
$this->offName($name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Exception;
|
||||
|
||||
|
||||
class AuthException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/25 0025
|
||||
* Time: 18:34
|
||||
*/
|
||||
|
||||
namespace Snowflake\Exception;
|
||||
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class ComponentException
|
||||
* @package Snowflake\Snowflake\Exception
|
||||
*/
|
||||
class ComponentException extends \Exception
|
||||
{
|
||||
|
||||
public function __construct(string $message = "", int $code = 0, Throwable $previous = NULL)
|
||||
{
|
||||
parent::__construct($message, 5000, $previous);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Exception;
|
||||
|
||||
|
||||
class ConfigException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Exception;
|
||||
|
||||
|
||||
class InitException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/24 0024
|
||||
* Time: 17:32
|
||||
*/
|
||||
|
||||
namespace Snowflake\Exception;
|
||||
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class NotFindClassException
|
||||
* @package Snowflake\Snowflake\Exception
|
||||
*/
|
||||
class NotFindClassException extends \Exception
|
||||
{
|
||||
|
||||
public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
|
||||
{
|
||||
$message = "No class named `$message` was found, please check if the class name is correct";
|
||||
parent::__construct($message, 404, $previous);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Exception;
|
||||
|
||||
|
||||
class RedisConnectException extends \Exception
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
<?php
|
||||
|
||||
namespace Snowflake\Jwt;
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Http\HttpHeaders;
|
||||
use Redis;
|
||||
use Snowflake\Core\Str;
|
||||
use Snowflake\Exception\AuthException;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
class Jwt extends Component
|
||||
{
|
||||
|
||||
/** @var int $user */
|
||||
private $user;
|
||||
|
||||
private $data;
|
||||
|
||||
private $source = ['browser', 'android', 'iphone', 'pc', 'mingame'];
|
||||
|
||||
private $config = ['token' => ''];
|
||||
|
||||
private $timeout = 7200;
|
||||
|
||||
private $public = '-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6BuML3gtLGde7QKNuNST
|
||||
UCB9gdHC7XIpOc7Wx2I64Esj3UxWHTgp3URj0ge8zpy7A3FfBdppR7d1nwoD6Xad
|
||||
jqfjEWpTy4WwGYsOfH0tFl3wAmse0lebF4NFsS9pzrikQT6c9qsVm88pCjvg4i5t
|
||||
WhTMEnpTFDYoDR0KXlLXltQMudBBUHFaVwP0wKJ/cGX7R1Mrv35K4MXwQFOuGZkP
|
||||
hsp2rO9x5LjtSKIXbexy7WhUu6QMjD/XzgsXr9UF+ExYmBGXRVWgNFLMkiaCZ2Uz
|
||||
WlQhpQrA5/wKd76dCzjvqw9M32OiZl2lCKT73cV8GUvt7BNsM1SiPhqfY7nhO6y3
|
||||
cwIDAQAB
|
||||
-----END PUBLIC KEY-----';
|
||||
|
||||
private $private = '-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEA6BuML3gtLGde7QKNuNSTUCB9gdHC7XIpOc7Wx2I64Esj3UxW
|
||||
HTgp3URj0ge8zpy7A3FfBdppR7d1nwoD6XadjqfjEWpTy4WwGYsOfH0tFl3wAmse
|
||||
0lebF4NFsS9pzrikQT6c9qsVm88pCjvg4i5tWhTMEnpTFDYoDR0KXlLXltQMudBB
|
||||
UHFaVwP0wKJ/cGX7R1Mrv35K4MXwQFOuGZkPhsp2rO9x5LjtSKIXbexy7WhUu6QM
|
||||
jD/XzgsXr9UF+ExYmBGXRVWgNFLMkiaCZ2UzWlQhpQrA5/wKd76dCzjvqw9M32Oi
|
||||
Zl2lCKT73cV8GUvt7BNsM1SiPhqfY7nhO6y3cwIDAQABAoIBADPihJHP8XktmmCs
|
||||
43Vfv5Z3zNaKR2LA1Eph3E0xviuJYHkFqXJarbESqqW2qRQeoQeB/lXWnxYzAo4M
|
||||
tRcpNss+6FlqRVUHi3gKR7C4Yq3PTemcfIVUpAy7gYa8LJDTYZRcJMZXNDtiMbBh
|
||||
9kFZU4SBhaTTx2KLQKS9yyWOqzbBvyLXN+1+Wy477M9+MXXTKw79dO+pML6cR0yl
|
||||
pNfVR5FX5L/GB5vOtQB/Aqg/CKT8NC5MzWPnKY+TPCCHZyoZuB9dLDuWOlqsN4QX
|
||||
Y4B8fFca5yRwzHra5aGoqdaT/zGctt+I6V/f/KNQCo36f9LPxeXg1+FHvvtTj5WZ
|
||||
N8CGPzECgYEA9R7lRMXzrHE4rK0DhxQXIFbIKKtxrimqZQdbwOUeYYD2R6CDSItK
|
||||
z88RSYElmd6wiS7fYIaheXNqJ8Yu6SQFBF/yshBwjQVl9NJG94LJlgx1XnVZEju6
|
||||
OZjMUOhHXBymtXnLo16pDRl8odc4MFLRH25/vLtwChUr+Qoyt54GzFUCgYEA8mjL
|
||||
jdh94JAmcdnDXsKgjNOGyNWGDVvWoFmy8lEQsMXY1JJnEd3YfDM2prmv3vaoiXzi
|
||||
YkSETl6ZUtJqh78MnHCBY1vI6EAcKQAF/kvP2TataRCXNcGNQwn2mtq+B+heTta6
|
||||
Di8jjAdmdUAYHbmOQryBudiRYG7JEF038elzvKcCgYEAq81ByFguGBkrLev94vkz
|
||||
1Fi+5bJ0dSuC4Fit+J8eEhz/gOiB26C1iL2LUkeQgS5R8XTG37K9DpDUQJhpXMMA
|
||||
OTa+tgtLt6um8FdJokUq4V5ODSyWh28RcTklSzfifC8gsWVyU0kPl7zbW9uq6EPD
|
||||
ixI5uaBuQMLiFSUOsx+xiBkCgYEAtqXHWeVZUy7KCNavomK7XeCzmfdovgAIw2FS
|
||||
t8nk7YzlR6XYC1pAl7Ru5Ujb/v+TFaUHXkuJ9RLKK+Fna0jEU8thcl/iDTzg+vON
|
||||
kIHG5j+Qga2CgXqI2Y5URXGz5XlsNbMNFUrnWcbpqEbW5O6/BgHLLSDEyQgwbygN
|
||||
0zS3g9kCgYEAhssb7kOljdIul4lY5MXc67Zf1dp6S2bucLOxsG6cRW07b3pBz7QF
|
||||
5aPE7ZwnkzTnA4HuGGauKj+qKGAR7ve55XClAq/XipiVFrjwV/t3LC6j5DoqTJYR
|
||||
mlAZUEjsoaT9vjvjGTxl3uCm0TX5KTgtSJIt2kA1tYVjQef+/iZTHxY=
|
||||
-----END RSA PRIVATE KEY-----';
|
||||
|
||||
/** @var Jwt */
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @param string $publicKey
|
||||
*/
|
||||
public function setPublic(string $publicKey)
|
||||
{
|
||||
$this->public = $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $timeout
|
||||
*/
|
||||
public function setTimeout(int $timeout)
|
||||
{
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $privateKey
|
||||
*/
|
||||
public function setPrivate(string $privateKey)
|
||||
{
|
||||
$this->private = $privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Jwt
|
||||
*/
|
||||
private static function getInstance()
|
||||
{
|
||||
if (!(static::$instance instanceof Jwt)) {
|
||||
static::$instance = new Jwt();
|
||||
}
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $unionId
|
||||
* @param $headers
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function create($unionId, $headers = [])
|
||||
{
|
||||
$this->user = $unionId;
|
||||
$this->config['time'] = time();
|
||||
if (empty($headers)) {
|
||||
$headers = request()->headers->getHeaders();
|
||||
} else if ($headers instanceof HttpHeaders) {
|
||||
$headers = $headers->getHeaders();
|
||||
}
|
||||
|
||||
$this->data = $headers;
|
||||
if (empty($unionId)) {
|
||||
throw new Exception('您还未登录或已登录超时');
|
||||
}
|
||||
$source = $header['source'] ?? 'browser';
|
||||
if (empty($source) || !in_array($source, $this->source)) {
|
||||
throw new Exception('未知的登录设备');
|
||||
}
|
||||
return $this->createEncrypt($unionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $unionId
|
||||
* @return array
|
||||
* @throws Exception
|
||||
* 对相关信息进行加密
|
||||
*/
|
||||
private function createEncrypt($unionId)
|
||||
{
|
||||
$caches = $this->clear($unionId);
|
||||
$param = $this->assembly(array_merge($this->config, [
|
||||
'user' => $unionId,
|
||||
'token' => $this->token($unionId, [
|
||||
'device' => Str::rand(128),
|
||||
], $this->config['time']),
|
||||
]), TRUE);
|
||||
$refresh = array_intersect_key($param, $this->config);
|
||||
|
||||
$params['user'] = $this->user;
|
||||
$params['token'] = $refresh['token'];
|
||||
$json = json_encode($params, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
openssl_private_encrypt($json, $encode, $this->private);
|
||||
$refresh['refresh'] = base64_encode($encode);
|
||||
$this->setRefresh($refresh['refresh']);
|
||||
|
||||
$redis = $this->getRedis();
|
||||
foreach ($caches as $cache) {
|
||||
$redis->del($cache);
|
||||
}
|
||||
|
||||
return $refresh;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $update
|
||||
* @param array $param
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
private function assembly(array $param, $update = FALSE)
|
||||
{
|
||||
if (isset($param['sign'])) {
|
||||
unset($param['sign']);
|
||||
}
|
||||
$param = $this->initialize($param);
|
||||
asort($param, SORT_STRING);
|
||||
$_tmp = [];
|
||||
foreach ($param as $key => $val) {
|
||||
$_tmp[] = trim($key) . '=>' . trim($val);
|
||||
}
|
||||
$param['sign'] = md5(implode(':', $_tmp));
|
||||
if ($update) {
|
||||
$this->setCache($param);
|
||||
}
|
||||
return $param;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $headers
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function refresh($headers = [])
|
||||
{
|
||||
$this->data = $headers;
|
||||
if (!openssl_public_decrypt(base64_decode($headers['refresh']), $data, $this->public)) {
|
||||
throw new Exception('信息解码失败.');
|
||||
}
|
||||
|
||||
$this->user = $data['user'];
|
||||
|
||||
if (!$this->getRedis()->exists('refresh:' . $this->user)) {
|
||||
throw new Exception('refresh data error.');
|
||||
}
|
||||
|
||||
$this->getRedis()->del('refresh:' . $this->user);
|
||||
|
||||
return $this->create($this->user, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $param
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function initialize(array $param)
|
||||
{
|
||||
$_param = [
|
||||
'version' => '1',
|
||||
'source' => $this->getSource(),
|
||||
];
|
||||
if (!isset($param['device'])) {
|
||||
$param['device'] = Str::rand(128);
|
||||
}
|
||||
return array_merge($_param, $param);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setCache(array $data)
|
||||
{
|
||||
$redis = $this->getRedis();
|
||||
$redis->hMset($this->authKey($this->getSource(), $data['token']), $data);
|
||||
$redis->expire($this->authKey($this->getSource(), $data['token']), $this->timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $refresh
|
||||
* @throws Exception
|
||||
*/
|
||||
private function setRefresh(string $refresh)
|
||||
{
|
||||
$redis = $this->getRedis();
|
||||
|
||||
$redis->set('refresh:' . $this->user, $refresh);
|
||||
$redis->expire('refresh:' . $this->user, $this->timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $_source
|
||||
* @param string $token
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function authKey($_source, $token)
|
||||
{
|
||||
$source = $this->getSource();
|
||||
if (!empty($_source)) $source = $_source;
|
||||
if (empty($source)) {
|
||||
throw new Exception("未知的登陆设备");
|
||||
}
|
||||
return 'Tmp_Token:' . strtoupper($source) . ':' . $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
return $this->data['source'] ?? 'browser';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $user
|
||||
* @param array $param
|
||||
* @param null $requestTime
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function token($user, $param = [], $requestTime = NULL)
|
||||
{
|
||||
$str = '';
|
||||
|
||||
$_user = str_split(md5($user . md5($user)));
|
||||
ksort($_user);
|
||||
foreach ($_user as $key => $val) {
|
||||
$str .= md5(sha1($key . $val . 'www.xshucai.com'));
|
||||
}
|
||||
foreach ($param as $key => $val) {
|
||||
$str .= md5($str . sha1($key . md5($val)));
|
||||
}
|
||||
$str .= sha1(base64_encode($requestTime));
|
||||
return $this->preg(md5($str . $user));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return mixed
|
||||
* 将字符串替换成指定格式
|
||||
*/
|
||||
private function preg($str)
|
||||
{
|
||||
$preg = '/(\w{10})(\w{3})(\w{4})(\w{9})(\w{6})/';
|
||||
return preg_replace($preg, '$1-$2-$3-$4-$5', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $user
|
||||
* @return string[]
|
||||
* @throws
|
||||
*/
|
||||
public function clear($user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$redis = $this->getRedis();
|
||||
$refresh = $redis->get('refresh:' . $this->user);
|
||||
openssl_public_decrypt(base64_decode($refresh), $info, $this->public);
|
||||
|
||||
$_tmp = [];
|
||||
if (!empty($info) && $json = json_decode($info, true)) {
|
||||
if (!isset($json['token'])) {
|
||||
return [];
|
||||
}
|
||||
foreach ($this->source as $value) {
|
||||
$_tmp[] = $this->authKey($value, $json['token']);
|
||||
}
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param int $user
|
||||
* @return bool
|
||||
* @throws
|
||||
*/
|
||||
public function check($data, $user)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->user = $user;
|
||||
|
||||
if (empty($this->user)) return FALSE;
|
||||
$cache = $this->getUserModel();
|
||||
if (empty($cache)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$merge = $this->assembly(array_merge($cache, [
|
||||
'token' => $data['token'],
|
||||
]));
|
||||
$check = array_diff_assoc($this->initialize($cache), $merge);
|
||||
return !((bool)count($check));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws
|
||||
*/
|
||||
public function getCurrentOnlineUser()
|
||||
{
|
||||
$this->data = request()->headers->getHeaders();
|
||||
$model = $this->getUserModel();
|
||||
if (empty($model)) {
|
||||
throw new AuthException('授权信息已过期!');
|
||||
}
|
||||
if (!isset($model['user'])) {
|
||||
throw new AuthException('授权信息错误!');
|
||||
}
|
||||
if (!$this->check($this->data, $model['user'])) {
|
||||
throw new AuthException('授权信息不合法!');
|
||||
}
|
||||
$this->expireRefresh();
|
||||
|
||||
return $model['user'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $header
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function checkAuth(array $header = [])
|
||||
{
|
||||
$instance = static::getInstance();
|
||||
if (empty($header)) {
|
||||
$header = request()->headers->getHeaders();
|
||||
}
|
||||
|
||||
$instance->data = $header;
|
||||
$model = $instance->getUserModel();
|
||||
if (empty($model) || !isset($model['user'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$instance->check($header, $model['user'])) {
|
||||
return false;
|
||||
}
|
||||
$instance->expireRefresh();
|
||||
return $model['user'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function expireRefresh()
|
||||
{
|
||||
$key = $this->authKey($this->getSource(), $this->data['token']);
|
||||
$this->getRedis()->expire($key, $this->timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|array
|
||||
* @throws AuthException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getUserModel()
|
||||
{
|
||||
if (!isset($this->data['token'])) {
|
||||
throw new AuthException('暂无访问权限!');
|
||||
}
|
||||
$key = $this->authKey($this->getSource(), $this->data['token']);
|
||||
return $this->getRedis()->hGetAll($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Redis
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getRedis()
|
||||
{
|
||||
return Snowflake::app()->getRedis();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Observer;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Observer
|
||||
* @package Snowflake\Observer
|
||||
*/
|
||||
class Observer extends Component
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Observer;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\ArrayAccess;
|
||||
use Snowflake\Core\Dtl;
|
||||
|
||||
/**
|
||||
* Class Subscribe
|
||||
* @package Snowflake\Observer
|
||||
*/
|
||||
class Subscribe extends Component
|
||||
{
|
||||
|
||||
public $subscribes = [];
|
||||
|
||||
public $params = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $callback
|
||||
* @param array $params
|
||||
* @return Subscribe
|
||||
* @throws Exception
|
||||
*/
|
||||
public function subscribe($name, $callback, array $params = [])
|
||||
{
|
||||
if (!is_callable($callback, true)) {
|
||||
throw new Exception('Subscribe must need callback.');
|
||||
}
|
||||
$this->subscribes[$name] = $callback;
|
||||
$this->params[$name] = $params;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
* @param null $name
|
||||
* @return mixed|void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function publish($name = null, $params = [])
|
||||
{
|
||||
if (empty($name)) {
|
||||
return $this->release_all($params);
|
||||
}
|
||||
if (!isset($this->subscribes[$name])) {
|
||||
throw new Exception('Subscribe ' . $name . ' not found.');
|
||||
}
|
||||
$merge = $this->merge($name, $params);
|
||||
return $this->subscribes[$name](new Dtl($merge));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
*/
|
||||
private function release_all($params)
|
||||
{
|
||||
foreach ($this->subscribes as $name => $subscribe) {
|
||||
$merge = $this->merge($this->params[$name] ?? [], $params);
|
||||
$subscribe(new Dtl($merge));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $params
|
||||
* @return mixed
|
||||
*/
|
||||
private function merge($name, $params)
|
||||
{
|
||||
if (!isset($this->params[$name])) {
|
||||
return $params;
|
||||
}
|
||||
return merge($this->params[$name], $params);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
<?php
|
||||
|
||||
namespace Snowflake\Pool;
|
||||
|
||||
use HttpServer\Http\Context;
|
||||
use PDO;
|
||||
use Exception;
|
||||
use Swoole\Coroutine;
|
||||
use Snowflake\Abstracts\Pool;
|
||||
|
||||
/**
|
||||
* Class Connection
|
||||
* @package Snowflake\Pool
|
||||
*/
|
||||
class Connection extends Pool
|
||||
{
|
||||
|
||||
public $hasCreate = [];
|
||||
|
||||
public $timeout = 1900;
|
||||
|
||||
/** @var PDO[] */
|
||||
protected $connections = [];
|
||||
|
||||
/**
|
||||
* @param $timeout
|
||||
*/
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setLength($value)
|
||||
{
|
||||
$this->max = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cds
|
||||
* @return bool
|
||||
*
|
||||
* db is in transaction
|
||||
*/
|
||||
public function inTransaction($cds)
|
||||
{
|
||||
[$coroutineId, $coroutineName] = $this->getIndex($cds, true);
|
||||
if (!Context::hasContext('begin_' . $coroutineName, $coroutineId)) {
|
||||
return false;
|
||||
}
|
||||
return Context::getContext('begin_' . $coroutineName, $coroutineId) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function beginTransaction($coroutineName)
|
||||
{
|
||||
[$coroutineId, $coroutineName] = $this->getIndex($coroutineName, true);
|
||||
if (!Context::hasContext('begin_' . $coroutineName, $coroutineId)) {
|
||||
Context::setContext('begin_' . $coroutineName, 0, $coroutineId);
|
||||
}
|
||||
if (Context::getContext('begin_' . $coroutineName, $coroutineId) === 0) {
|
||||
$connection = Context::getContext($coroutineName);
|
||||
if ($connection instanceof PDO && !$connection->inTransaction()) {
|
||||
$connection->beginTransaction();
|
||||
}
|
||||
}
|
||||
Context::autoIncr('begin_' . $coroutineName, $coroutineId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function commit($coroutineName)
|
||||
{
|
||||
[$coroutineId, $coroutineName] = $this->getIndex($coroutineName, true);
|
||||
if (!Context::hasContext('begin_' . $coroutineName, $coroutineId)) {
|
||||
return;
|
||||
}
|
||||
if (Context::autoDecr('begin_' . $coroutineName, $coroutineId) > 0) {
|
||||
return;
|
||||
}
|
||||
$connection = Context::getContext($coroutineName);
|
||||
if ($connection instanceof PDO) {
|
||||
if ($connection->inTransaction()) {
|
||||
$this->info('connection commit.');
|
||||
$connection->commit();
|
||||
}
|
||||
Context::setContext('begin_' . $coroutineName, 0, $coroutineId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineId
|
||||
* @param $coroutineName
|
||||
* @return array
|
||||
*/
|
||||
private function instanceTrance($coroutineId, $coroutineName)
|
||||
{
|
||||
return [$coroutineId, $coroutineName];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param false $isMaster
|
||||
* @return array
|
||||
*/
|
||||
private function getIndex($name, $isMaster = false)
|
||||
{
|
||||
return $this->instanceTrance(Coroutine::getCid(), $this->name($name, $isMaster));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function rollback($coroutineName)
|
||||
{
|
||||
[$coroutineId, $coroutineName] = $this->getIndex($coroutineName, true);
|
||||
if (!Context::hasContext('begin_' . $coroutineName, $coroutineId)) {
|
||||
return;
|
||||
}
|
||||
if (Context::autoDecr('begin_' . $coroutineName, $coroutineId) > 0) {
|
||||
return;
|
||||
}
|
||||
if ($this->hasClient($coroutineName)) {
|
||||
/** @var PDO $connection */
|
||||
$connection = Context::getContext($coroutineName);
|
||||
if ($connection->inTransaction()) {
|
||||
$this->info('connection rollBack.');
|
||||
$connection->rollBack();
|
||||
}
|
||||
}
|
||||
Context::setContext('begin_' . $coroutineName, 0, $coroutineId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param bool $isMaster
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnection(array $config, $isMaster = false)
|
||||
{
|
||||
[$coroutineId, $coroutineName] = $this->getIndex($config['cds'], $isMaster);
|
||||
if (Context::hasContext($coroutineName)) {
|
||||
return Context::getContext($coroutineName);
|
||||
} else if (!$this->hasItem($coroutineName)) {
|
||||
return $this->saveClient($coroutineName, $this->nowClient($coroutineName, $config));
|
||||
} else {
|
||||
return $this->getByChannel($coroutineName, $config);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $config
|
||||
* @return Connection
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fill($name, $config)
|
||||
{
|
||||
if ($this->hasLength($name) >= 10) {
|
||||
return $this;
|
||||
}
|
||||
for ($i = 0; $i < 10 - $this->hasLength($name); $i++) {
|
||||
$this->push($name, $this->createConnect($config['cds'], $config['username'], $config['password']));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @param $config
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getByChannel($coroutineName, $config)
|
||||
{
|
||||
$this->info('client has :' . $this->hasLength($coroutineName));
|
||||
[$time, $client] = $this->get($coroutineName, -1);
|
||||
if ($client instanceof PDO) {
|
||||
return $this->saveClient($coroutineName, $client);
|
||||
}
|
||||
unset($client);
|
||||
if (!$this->hasItem($coroutineName)) {
|
||||
return $this->saveClient($coroutineName, $this->nowClient($coroutineName, $config));
|
||||
}
|
||||
return $this->getByChannel($coroutineName, $config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @param $client
|
||||
* @return mixed
|
||||
*/
|
||||
private function saveClient($coroutineName, $client)
|
||||
{
|
||||
return Context::setContext($coroutineName, $client);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @param $config
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
private function nowClient($coroutineName, $config)
|
||||
{
|
||||
$client = $this->createConnect($config['cds'], $config['username'], $config['password']);
|
||||
$this->success('create db client -> ' . $config['cds'] . ':' . $this->hasLength($coroutineName));
|
||||
if (isset(Context::getContext('begin_' . $coroutineName)[Coroutine::getCid()])) {
|
||||
$number = Context::getContext('begin_' . $coroutineName)[Coroutine::getCid()];
|
||||
$number > 0 && $client->beginTransaction();
|
||||
}
|
||||
$this->incr($coroutineName);
|
||||
return $client;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @param $isMaster
|
||||
*/
|
||||
public function release($coroutineName, $isMaster)
|
||||
{
|
||||
[$coroutineId, $coroutineName] = $this->getIndex($coroutineName, $isMaster);
|
||||
if (!$this->hasClient($coroutineName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var PDO $client */
|
||||
$client = Context::getContext($coroutineName);
|
||||
if ($client->inTransaction()) {
|
||||
$client->commit();
|
||||
}
|
||||
$this->push($coroutineName, $client);
|
||||
$this->remove($coroutineName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @return bool
|
||||
*/
|
||||
private function hasClient($coroutineName)
|
||||
{
|
||||
return Context::hasContext($coroutineName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* batch release
|
||||
*/
|
||||
public function connection_clear()
|
||||
{
|
||||
$this->debug('receive all clients.');
|
||||
$connections = Context::getAllContext();
|
||||
foreach ($connections as $name => $connection) {
|
||||
if (empty($connection) || !($connection instanceof PDO)) {
|
||||
continue;
|
||||
}
|
||||
/** @var PDO $pdoClient */
|
||||
if ($connection->inTransaction()) {
|
||||
$connection->commit();
|
||||
}
|
||||
$this->push($name, $connection);
|
||||
$this->remove($name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function remove($coroutineName)
|
||||
{
|
||||
Context::deleteId($coroutineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $time
|
||||
* @param $connect
|
||||
* @return bool
|
||||
*/
|
||||
public function checkCanUse($time, $connect)
|
||||
{
|
||||
try {
|
||||
if ($time + 60 * 10 < time()) {
|
||||
return false;
|
||||
}
|
||||
if (empty($connect) || !($connect instanceof PDO)) {
|
||||
return false;
|
||||
}
|
||||
if (!$connect->getAttribute(PDO::ATTR_SERVER_INFO)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (\Swoole\Error | \Throwable $exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $cds
|
||||
* @param $username
|
||||
* @param $password
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createConnect($cds, $username, $password)
|
||||
{
|
||||
try {
|
||||
$link = new PDO($cds, $username, $password, [
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
// PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
|
||||
PDO::ATTR_CASE => PDO::CASE_NATURAL,
|
||||
PDO::ATTR_TIMEOUT => $this->timeout,
|
||||
]);
|
||||
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$link->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
|
||||
$link->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
|
||||
return $link;
|
||||
} catch (\Throwable $exception) {
|
||||
if ($exception->getCode() !== 2006) {
|
||||
$this->addError($cds . ' -> ' . $exception->getMessage());
|
||||
throw new Exception($exception->getMessage());
|
||||
}
|
||||
$this->addError($cds . ' -> ' . $exception->getMessage());
|
||||
return $this->createConnect($cds, $username, $password);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function disconnect($coroutineName)
|
||||
{
|
||||
if (!$this->hasClient($coroutineName)) {
|
||||
return;
|
||||
}
|
||||
$this->remove($coroutineName);
|
||||
$this->clean($coroutineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function incr($coroutineName)
|
||||
{
|
||||
if (!isset($this->hasCreate[$coroutineName])) {
|
||||
$this->hasCreate[$coroutineName] = 0;
|
||||
}
|
||||
$this->hasCreate[$coroutineName] += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function desc($coroutineName)
|
||||
{
|
||||
if (!isset($this->hasCreate[$coroutineName])) {
|
||||
$this->hasCreate[$coroutineName] = 0;
|
||||
}
|
||||
$this->hasCreate[$coroutineName] -= 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Pool;
|
||||
|
||||
|
||||
use Snowflake\Cache\Memcached;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Pool
|
||||
* @package Snowflake\Pool
|
||||
* @property $redis
|
||||
* @property $db
|
||||
* @property $memcached
|
||||
*/
|
||||
class Pool extends \Snowflake\Abstracts\Pool
|
||||
{
|
||||
|
||||
/**
|
||||
* @return Redis
|
||||
*/
|
||||
public function getRedis()
|
||||
{
|
||||
return Snowflake::app()->redis_connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Connection
|
||||
*/
|
||||
public function getDb()
|
||||
{
|
||||
return Snowflake::app()->connections;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Memcached
|
||||
*/
|
||||
public function getMemcached()
|
||||
{
|
||||
return Snowflake::app()->memcached;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Pool;
|
||||
|
||||
|
||||
use HttpServer\Http\Context;
|
||||
use Redis as SRedis;
|
||||
use RedisException;
|
||||
use Snowflake\Exception\RedisConnectException;
|
||||
use Swoole\Coroutine;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class RedisClient
|
||||
* @package Snowflake\Snowflake\Pool
|
||||
*/
|
||||
class Redis extends Pool
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setLength($value)
|
||||
{
|
||||
$this->max = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param bool $isMaster
|
||||
* @return mixed|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnection(array $config, $isMaster = false)
|
||||
{
|
||||
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
|
||||
[$coroutineId, $coroutineName] = $this->getIndex('redis:' . $name, $isMaster);
|
||||
if (Context::hasContext($coroutineName)) {
|
||||
return Context::getContext($coroutineName);
|
||||
} else if (!$this->hasItem($coroutineName)) {
|
||||
$this->success('create redis client -> ' . $config['host'] . ':' . $this->hasLength($coroutineName));
|
||||
return $this->saveClient($coroutineName, $this->createConnect($config));
|
||||
}
|
||||
return $this->getByChannel($coroutineName, $config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @param $config
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getByChannel($coroutineName, $config)
|
||||
{
|
||||
$this->info('redis client has :' . $this->hasLength($coroutineName));
|
||||
if (!$this->hasItem($coroutineName)) {
|
||||
$this->success('create redis client -> ' . $config['host'] . ':' . $this->hasLength($coroutineName));
|
||||
return $this->saveClient($coroutineName, $this->createConnect($config));
|
||||
}
|
||||
[$time, $client] = $this->get($coroutineName, -1);
|
||||
if ($client === null) {
|
||||
return $this->getByChannel($coroutineName, $config);
|
||||
}
|
||||
return $this->saveClient($coroutineName, $client);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
* @param $client
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function saveClient($coroutineName, $client)
|
||||
{
|
||||
return Context::setContext($coroutineName, $client);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @return SRedis
|
||||
* @throws Exception
|
||||
*/
|
||||
private function createConnect(array $config)
|
||||
{
|
||||
$redis = new SRedis();
|
||||
if (!$redis->connect($config['host'], $config['port'], $config['timeout'])) {
|
||||
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $config['host'], $config['port']));
|
||||
}
|
||||
if (empty($config['auth']) || !$redis->auth($config['auth'])) {
|
||||
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $config['host'], $config['auth']));
|
||||
}
|
||||
if (!isset($config['read_timeout'])) {
|
||||
$config['read_timeout'] = 10;
|
||||
}
|
||||
$redis->select($config['databases']);
|
||||
$redis->setOption(SRedis::OPT_READ_TIMEOUT, -1);
|
||||
$redis->setOption(SRedis::OPT_PREFIX, $config['prefix']);
|
||||
return $redis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param bool $isMaster
|
||||
*/
|
||||
public function release(array $config, $isMaster = false)
|
||||
{
|
||||
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
|
||||
[$coroutineId, $coroutineName] = $this->getIndex('redis:' . $name, $isMaster);
|
||||
if (!Context::hasContext($coroutineName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$client = Context::getContext($coroutineName);
|
||||
|
||||
$this->push($coroutineName, $client);
|
||||
$this->remove($coroutineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param bool $isMaster
|
||||
*/
|
||||
public function destroy(array $config, $isMaster = false)
|
||||
{
|
||||
$name = $config['host'] . ':' . $config['prefix'] . ':' . $config['databases'];
|
||||
[$coroutineId, $coroutineName] = $this->getIndex('redis:' . $name, $isMaster);
|
||||
if (!Context::hasContext($coroutineName)) {
|
||||
return;
|
||||
}
|
||||
$this->remove($coroutineName);
|
||||
$this->clean($coroutineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $coroutineName
|
||||
*/
|
||||
public function remove($coroutineName)
|
||||
{
|
||||
Context::deleteId($coroutineName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $time
|
||||
* @param $client
|
||||
* @return bool|mixed
|
||||
* @throws RedisException
|
||||
*/
|
||||
public function checkCanUse($time, $client)
|
||||
{
|
||||
if ($time + 60 * 10 < time()) {
|
||||
return false;
|
||||
}
|
||||
if (!($client instanceof SRedis)) {
|
||||
return false;
|
||||
}
|
||||
if (!$client->isConnected() || !$client->ping('connect.')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function desc($name)
|
||||
{
|
||||
// TODO: Implement desc() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param false $isMaster
|
||||
* @return array
|
||||
*/
|
||||
private function getIndex($name, $isMaster = false)
|
||||
{
|
||||
return [Coroutine::getCid(), $this->name($name, $isMaster)];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Process;
|
||||
|
||||
|
||||
interface ISystem
|
||||
{
|
||||
|
||||
public function start();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Process;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Timer;
|
||||
|
||||
/**
|
||||
* Class Logfilemonitoring
|
||||
*/
|
||||
class Leafleting extends Process
|
||||
{
|
||||
|
||||
/**
|
||||
* @param \Swoole\Process $process
|
||||
* @return mixed|void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(\Swoole\Process $process)
|
||||
{
|
||||
Timer::tick(1000, function () use ($process) {
|
||||
var_dump($process->read());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Process;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Application;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Swoole\Coroutine\Socket;
|
||||
use Swoole\Process\Pool;
|
||||
|
||||
/**
|
||||
* Class Process
|
||||
* @package Snowflake\Snowflake\Service
|
||||
*/
|
||||
abstract class Process extends Component
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-22
|
||||
* Time: 19:09
|
||||
*/
|
||||
|
||||
namespace Snowflake\Process;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Event;
|
||||
use Swoole\Server;
|
||||
use Swoole\Timer;
|
||||
use swoole_process;
|
||||
|
||||
/**
|
||||
* Class ServerInotify
|
||||
* @package Snowflake\Snowflake\Server
|
||||
*/
|
||||
class ServerInotify extends Process
|
||||
{
|
||||
private $inotify;
|
||||
private $isReloading = false;
|
||||
private $isReloadingOut = false;
|
||||
private $watchFiles = [];
|
||||
private $dirs = [];
|
||||
private $events;
|
||||
|
||||
private $int = -1;
|
||||
|
||||
/**
|
||||
* @param \Swoole\Process $process
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(\Swoole\Process $process)
|
||||
{
|
||||
Snowflake::setProcessId($process->pid);
|
||||
if (extension_loaded('inotify')) {
|
||||
$this->inotify = inotify_init();
|
||||
$this->events = IN_MODIFY | IN_DELETE | IN_CREATE | IN_MOVE;
|
||||
$process->name('event: file change.');
|
||||
|
||||
$this->watch(APP_PATH);
|
||||
Event::add($this->inotify, [$this, 'check']);
|
||||
Event::wait();
|
||||
} else {
|
||||
$this->loadByDir(APP_PATH . 'app');
|
||||
Timer::tick(2000, [$this, 'tick']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private $md5Map = [];
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function tick()
|
||||
{
|
||||
$this->loadByDir(APP_PATH . 'app', true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param bool $isReload
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function loadByDir($path, $isReload = false)
|
||||
{
|
||||
$path = rtrim($path, '/');
|
||||
if ($this->isReloading) {
|
||||
return;
|
||||
}
|
||||
foreach (glob($path . '/*') as $value) {
|
||||
if (is_dir($value)) {
|
||||
$this->loadByDir($value, $isReload);
|
||||
continue;
|
||||
}
|
||||
$md5 = md5($value);
|
||||
$mTime = filectime($value);
|
||||
if (!isset($this->md5Map[$md5])) {
|
||||
if ($isReload) {
|
||||
return $this->reload();
|
||||
}
|
||||
$this->md5Map[$md5] = $mTime;
|
||||
} else {
|
||||
if ($this->md5Map[$md5] != $mTime) {
|
||||
if ($isReload) {
|
||||
return $this->reload();
|
||||
}
|
||||
$this->md5Map[$md5] = $mTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始监听
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
if (!($events = inotify_read($this->inotify))) {
|
||||
return;
|
||||
}
|
||||
if ($this->isReloading) {
|
||||
if (!$this->isReloadingOut) {
|
||||
$this->isReloadingOut = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$eventList = [IN_CREATE, IN_DELETE, IN_MODIFY, IN_MOVED_TO, IN_MOVED_FROM];
|
||||
foreach ($events as $ev) {
|
||||
if (empty($ev['name'])) {
|
||||
continue;
|
||||
}
|
||||
if ($ev['mask'] == IN_IGNORED) {
|
||||
continue;
|
||||
} else if (in_array($ev['mask'], $eventList)) {
|
||||
$fileType = strstr($ev['name'], '.');
|
||||
//非重启类型
|
||||
if ($fileType !== '.php') {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if ($this->int !== -1) {
|
||||
return;
|
||||
}
|
||||
$this->int = @swoole_timer_after(2000, [$this, 'reload']);
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
|
||||
$this->isReloading = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function reload()
|
||||
{
|
||||
$this->isReloading = true;
|
||||
|
||||
//清理所有监听
|
||||
$this->trigger_reload();
|
||||
$this->clearWatch();
|
||||
|
||||
//重新监听
|
||||
foreach ($this->dirs as $root) {
|
||||
$this->watch($root);
|
||||
}
|
||||
|
||||
$this->int = -1;
|
||||
$this->isReloading = FALSE;
|
||||
$this->isReloadingOut = FALSE;
|
||||
|
||||
$this->loadByDir(APP_PATH . 'app');
|
||||
}
|
||||
|
||||
/**
|
||||
* 重启
|
||||
*/
|
||||
public function trigger_reload()
|
||||
{
|
||||
/** @var Server $server */
|
||||
$server = Snowflake::app()->get('server')->getServer();
|
||||
$server->reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理所有inotify监听
|
||||
*/
|
||||
public function clearWatch()
|
||||
{
|
||||
try {
|
||||
foreach ($this->watchFiles as $wd) {
|
||||
@inotify_rm_watch($this->inotify, $wd);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
$this->watchFiles = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $dir
|
||||
* @param bool $root
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function watch($dir, $root = TRUE)
|
||||
{
|
||||
//目录不存在
|
||||
if (!is_dir($dir)) {
|
||||
throw new Exception("[$dir] is not a directory.");
|
||||
}
|
||||
//避免重复监听
|
||||
if (isset($this->watchFiles[$dir])) {
|
||||
return FALSE;
|
||||
}
|
||||
//根目录
|
||||
if ($root) {
|
||||
$this->dirs[] = $dir;
|
||||
}
|
||||
|
||||
if (in_array($dir, [APP_PATH . '/config', APP_PATH . '/commands', APP_PATH . '/.git', APP_PATH . '/.gitee'])) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$wd = @inotify_add_watch($this->inotify, $dir, $this->events);
|
||||
$this->watchFiles[$dir] = $wd;
|
||||
|
||||
$files = scandir($dir);
|
||||
foreach ($files as $f) {
|
||||
if ($f == '.' or $f == '..' or $f == 'runtime' or preg_match('/\.txt/', $f) or preg_match('/\.sql/', $f) or preg_match('/\.log/', $f)) {
|
||||
continue;
|
||||
}
|
||||
$path = $dir . '/' . $f;
|
||||
//递归目录
|
||||
if (is_dir($path)) {
|
||||
$this->watch($path, FALSE);
|
||||
}
|
||||
|
||||
//检测文件类型
|
||||
$fileType = strstr($f, '.');
|
||||
if ($fileType == '.php') {
|
||||
try {
|
||||
$wd = @inotify_add_watch($this->inotify, $path, $this->events);
|
||||
$this->watchFiles[$path] = $wd;
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake\Process;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
abstract class System extends Component implements ISystem
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use Snowflake\Process\Leafleting;
|
||||
use Snowflake\Process\ServerInotify;
|
||||
|
||||
return [
|
||||
|
||||
'processes' => [
|
||||
'Leafleting' => Leafleting::class,
|
||||
'inotify' => ServerInotify::class,
|
||||
]
|
||||
|
||||
];
|
||||
@@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Snowflake;
|
||||
|
||||
|
||||
use Exception;
|
||||
use ReflectionException;
|
||||
use Snowflake\Di\Container;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Swoole\Coroutine;
|
||||
|
||||
class Snowflake
|
||||
{
|
||||
|
||||
/** @var Container */
|
||||
public static $container;
|
||||
|
||||
|
||||
/** @var Application */
|
||||
private static $service;
|
||||
|
||||
|
||||
/**
|
||||
* @param $service
|
||||
*
|
||||
* 初始化服务
|
||||
*/
|
||||
public static function init($service)
|
||||
{
|
||||
static::$service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public static function app()
|
||||
{
|
||||
return static::$service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public static function has($name)
|
||||
{
|
||||
return static::$service->has($name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $className
|
||||
* @param $id
|
||||
*/
|
||||
public static function setAlias($className, $id)
|
||||
{
|
||||
return static::$service->setAlias($className, $id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $className
|
||||
* @param array $construct
|
||||
* @return mixed
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function createObject($className, $construct = [])
|
||||
{
|
||||
if (is_string($className)) {
|
||||
return static::$container->get($className, $construct);
|
||||
} else if (is_array($className)) {
|
||||
if (!isset($className['class']) || empty($className['class'])) {
|
||||
throw new Exception('Object configuration must be an array containing a "class" element.');
|
||||
}
|
||||
$class = $className['class'];
|
||||
unset($className['class']);
|
||||
return static::$container->get($class, $construct, $className);
|
||||
} else if (is_callable($className, TRUE)) {
|
||||
return call_user_func($className, $construct);
|
||||
} else {
|
||||
throw new Exception('Unsupported configuration type: ' . gettype($className));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function getStoragePath()
|
||||
{
|
||||
$path = realpath(static::$service->storage);
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function inCoroutine()
|
||||
{
|
||||
return Coroutine::getCid() > 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Container
|
||||
*/
|
||||
public static function getDi()
|
||||
{
|
||||
return static::$container;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $workerId
|
||||
* @return false|int|mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function setProcessId($workerId)
|
||||
{
|
||||
return self::writeFile(storage('socket.sock'), $workerId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $fileName
|
||||
* @param $content
|
||||
* @param null $is_append
|
||||
* @return false|int|mixed
|
||||
*/
|
||||
public static function writeFile($fileName, $content, $is_append = null)
|
||||
{
|
||||
$params = [$fileName, $content];
|
||||
if ($is_append !== null) {
|
||||
$params[] = $is_append;
|
||||
}
|
||||
return !self::inCoroutine() ? file_put_contents(...$params) : Coroutine::writeFile(...$params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $object
|
||||
* @param $config
|
||||
* @return mixed
|
||||
*/
|
||||
public static function configure($object, $config)
|
||||
{
|
||||
foreach ($config as $key => $value) {
|
||||
if (!property_exists($object, $key)) {
|
||||
continue;
|
||||
}
|
||||
$object->$key = $value;
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
|
||||
public static function clearProcessId($worker_pid)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function rename($tmp)
|
||||
{
|
||||
$hash = md5_file($tmp['tmp_name']);
|
||||
|
||||
$later = '.' . exif_imagetype($tmp['tmp_name']);
|
||||
|
||||
$match = '/(\w{12})(\w{5})(\w{9})(\w{6})/';
|
||||
$tmp = preg_replace($match, '$1-$2-$3-$4', $hash);
|
||||
|
||||
return strtoupper($tmp) . $later;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function isMac()
|
||||
{
|
||||
$output = strtolower(PHP_OS | PHP_OS_FAMILY);
|
||||
if (strpos('mac', $output) !== false) {
|
||||
return true;
|
||||
} else if (strpos('darwin', $output) !== false) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function isLinux()
|
||||
{
|
||||
if (!static::isMac()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function reload()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Snowflake::$container = new Container();
|
||||
Reference in New Issue
Block a user