This commit is contained in:
2020-08-31 01:27:08 +08:00
parent d6d4027b0d
commit e4f01d9499
119 changed files with 12232 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace Snowflake\Abstracts;
/**
* Class BaseAnnotation
* @package BeReborn\Annotation\Base
*/
abstract class BaseAnnotation extends Component
{
public function each()
{
}
}
+251
View File
@@ -0,0 +1,251 @@
<?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\Config;
use Snowflake\Di\Service;
use Snowflake\Error\ErrorHandler;
use Snowflake\Error\Logger;
use Snowflake\Exception\ComponentException;
use Snowflake\Pool\Connection;
use Snowflake\Pool\RedisClient;
use Snowflake\Processes;
use Snowflake\Snowflake;
use Snowflake\Event;
/**
* Class BaseApplication
* @package BeReborn\Base
* @property $json
* @property Annotation $annotation
* @property Event $event
* @property Router $router
* @property Processes $processes
* @property \Snowflake\Pool\Pool $pool
* @property Server $servers
* @property Connection $connections
*/
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 (isset($config['id'])) {
// $this->id = $config['id'];
// unset($config['id']);
// }
// if (isset($config['storage'])) {
// $this->storage = $config['storage'];
// unset($config['storage']);
// }
// if (!empty($this->runtimePath)) {
// if (!is_dir($this->runtimePath)) {
// mkdir($this->runtimePath, 777);
// }
//
// if (!is_dir($this->runtimePath) || !is_writeable($this->runtimePath)) {
// throw new InitException("Directory {$this->runtimePath} does not have write permission");
// }
// }
// if (isset($config['aliases'])) {
// $this->classAlias($config);
// }
//
// foreach ($this->moreComponents() as $key => $val) {
// if (isset($config['components'][$key])) {
// $config['components'][$key] = array_merge($val, $config['components'][$key]);
// } else {
// $config['components'][$key] = $val;
// }
// }
}
/**
* @param array $data
*/
private function classAlias(array &$data)
{
foreach ($data['aliases'] as $key => $val) {
class_alias($val, $key, true);
}
unset($data['aliases']);
}
/**
* @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());
}
/**
* @param $ip
* @return bool
*/
public function isLocal($ip)
{
return $this->getFirstLocal() == $ip;
}
/**
* @throws Exception
*/
protected function moreComponents()
{
return $this->setComponents([
'error' => ['class' => ErrorHandler::class],
'event' => ['class' => Event::class],
'annotation' => ['class' => Annotation::class],
'processes' => ['class' => Processes::class],
'connections' => ['class' => Connection::class],
'redis_connections' => ['class' => RedisClient::class],
'pool' => ['class' => \Snowflake\Pool\Pool::class],
'response' => ['class' => Response::class],
'request' => ['class' => Request::class],
'config' => ['class' => Config::class],
'logger' => ['class' => Logger::class],
'router' => ['class' => Router::class],
]);
}
}
+211
View File
@@ -0,0 +1,211 @@
<?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 BeReborn\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;
Logger::trance($message, 'debug');
}
/**
* @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;
Logger::trance($message, 'info');
}
/**
* @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;
Logger::trance($message, 'success');
}
/**
* @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;
Logger::trance($message, 'warning');
}
/**
* @param string $message
* @param string|null $method
* @param string|null $file
* @throws Exception
*/
public function error($message, string $method = null, string $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;
Logger::error($message, 'error');
}
}
+145
View File
@@ -0,0 +1,145 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:28
*/
namespace Snowflake\Abstracts;
use Exception;
/**
* Class Component
* @package BeReborn\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)
{
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]);
of($name, $_event);
}
}
}
fire($name, $event);
}
/**
* @param $name
* @param null $handler
* @return mixed
*/
public function off($name, $handler = NULL)
{
if (!isset($this->_events[$name])) {
return of($name, $handler);
}
if (empty($handler)) {
unset($this->_events[$name]);
return of($name, $handler);
}
foreach ($this->_events[$name] as $key => $val) {
if ($val[0] != $handler) {
continue;
}
unset($this->_events[$name][$key]);
break;
}
return of($name, $handler);
}
/**
*/
public function offAll()
{
$this->_events = [];
ofAll();
}
/**
* @param $name
* @return mixed
* @throws Exception
*/
public function __get($name)
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->$method();
} else if (property_exists($this, $name)) {
return $this->$name ?? null;
} else {
return parent::__get($name);
}
}
}
+85
View File
@@ -0,0 +1,85 @@
<?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 BeReborn\Base
*/
class Config extends Component
{
const ERROR_MESSAGE = 'The not find :key in app configs.';
public $data;
/**
* @param $key
* @param bool $try
* @param mixed $default
* @return null
* @throws
*/
public static function get($key, $try = FALSE, $default = null)
{
$config = Snowflake::get()->config;
if (isset($config->data[$key])) {
return $config->data[$key];
} else if ($default !== null) {
return $default;
} else if ($try) {
throw new ConfigException(str_replace(':key', $key, self::ERROR_MESSAGE));
}
return NULL;
}
/**
* @param $key
* @param $value
* @return mixed
* @throws Exception
*/
public static function set($key, $value)
{
$config = Snowflake::get()->config;
return $config->data[$key] = $value;
}
/**
* @param $key
* @param bool $must_not_null
* @return bool
*/
public static function has($key, $must_not_null = false)
{
$config = Snowflake::get()->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;
}
}
+18
View File
@@ -0,0 +1,18 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:11
*/
namespace Snowflake\Abstracts;
/**
* Interface Configure
* @package BeReborn\Base
*/
interface Configure
{
}
+156
View File
@@ -0,0 +1,156 @@
<?php
namespace Snowflake\Abstracts;
use Exception;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
/**
* Class Pool
* @package BeReborn\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
*/
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);
}
}
}
+149
View File
@@ -0,0 +1,149 @@
<?php
namespace Snowflake\Annotation;
use Exception;
use ReflectionClass;
use ReflectionException;
use Snowflake\Abstracts\BaseAnnotation;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
/**
* Class Annotation
* @package BeReborn\Annotation
* @property Websocket $websocket
*/
class Annotation extends BaseAnnotation
{
protected $_Scan_directory = [];
public $namespace = '';
public $prefix = '';
public $path = '';
private $_classMap = [
'websocket' => Websocket::class
];
/**
* @param $name
* @param $class
*/
public function register($name, $class)
{
$this->_classMap[$name] = $class;
}
/**
* @throws ReflectionException
*/
public function registration_notes()
{
if (!is_array($this->path)) {
return;
}
foreach ($this->path as $item) {
$this->scanning($item);
}
}
/**
* @param string $path
* @throws ReflectionException
* @throws Exception
*/
protected function scanning($path = '')
{
if (empty($path)) {
$path = rtrim($this->path, '/');
}
foreach (glob($path . '/*') as $file) {
if (is_dir($file)) {
$this->scanning($path);
}
$explode = explode('/', $file);
$class = str_replace('.php', '', end($explode));
$reflect = new ReflectionClass($this->namespace . $class);
$methods = $reflect->getMethods(\ReflectionMethod::IS_PUBLIC);
if (empty($methods) || !$reflect->isInstantiable()) {
continue;
}
$this->resolve($reflect, $methods);
}
}
/**
* @param ReflectionClass $class
* @param array $methods
* @throws Exception
*/
public function resolve(ReflectionClass $class, array $methods)
{
throw new Exception('Undefined analytic function.');
}
/**
* @param $path
* @param mixed ...$param
* @return bool|mixed
*/
public function runWith($path, $param)
{
if (!$this->has($path)) {
return null;
}
return call_user_func($this->_Scan_directory[$path], ...$param);
}
/**
* @param $name
* @param $callback
*/
public function push($name, $callback)
{
$this->_Scan_directory[$name] = $callback;
}
/**
* @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 Snowflake::createObject($this->_classMap[$name]);
}
return parent::__get($name); // TODO: Change the autogenerated stub
}
}
@@ -0,0 +1,66 @@
<?php
namespace Snowflake\Annotation;
use ReflectionClass;
/**
* Class Websocket
* @package Snowflake\Annotation
*/
class Websocket extends Annotation
{
const MESSAGE = 'WEBSOCKET:MESSAGE:';
const EVENT = 'WEBSOCKET:EVENT:';
public $Message;
public $Event;
/**
* @param ReflectionClass $reflect
* @param array $methods
*/
public function resolve(ReflectionClass $reflect, array $methods)
{
$controller = $reflect->newInstance();
foreach ($methods as $function) {
$comment = $function->getDocComment();
$methodName = $function->getName();
preg_match('/@Event\((.*)?\)/', $comment, $events);
if (!isset($events[1])) {
continue;
}
if (!($_key = $this->getName($events, $comment))) {
continue;
}
$this->push($_key, [$controller, $methodName]);
}
}
/**
* @param $events
* @param $comment
* @return false|string
*/
private function getName($events, $comment)
{
$event = $events[1];
if ($event !== 'message') {
return self::EVENT . $event;
}
preg_match('/@Message\((.*)?\)/', $comment, $message);
if (isset($message[1])) {
return false;
}
return self::MESSAGE . $message[1];
}
}
+71
View File
@@ -0,0 +1,71 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/4/25 0025
* Time: 18:38
*/
namespace Snowflake;
use Exception;
use HttpServer\Abstracts\HttpService;
use HttpServer\Server;
use Snowflake\Abstracts\BaseApplication;
/**
* Class Init
*
* @package BeReborn\Web
*
* @property-read Config $config
*/
class Application extends BaseApplication
{
/**
* @var string
*/
public $id = 'uniqueId';
/**
* @throws Exception
*/
public function init()
{
$process = Snowflake::get()->processes;
if (Config::has('servers', true)) {
/** @var Server $https */
$https = $this->make(Server::class);
$servers = $https->initCore(Config::get('servers'));
$process->push($servers);
}
if (Config::has('processes', true)) {
$process->push(Config::get('processes'));
}
}
/**
* @throws Exception
*/
public function start()
{
$process = Snowflake::get()->processes;
$process->start();
}
/**
* @param $className
* @param null $abstracts
* @return mixed
* @throws Exception
*/
public function make($className, $abstracts = null)
{
return Snowflake::createObject($className);
}
}
+147
View File
@@ -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 BeReborn\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');
}
}
+64
View File
@@ -0,0 +1,64 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/11/8 0008
* Time: 16:35
*/
namespace Snowflake\Cache;
/**
* Interface ICache
* @package BeReborn\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);
}
+117
View File
@@ -0,0 +1,117 @@
<?php
namespace Snowflake\Cache;
use Exception;
use Snowflake\Abstracts\Component;
/**
* 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()
{
$this->_memcached = new \Memcached();
$isConnected = $this->_memcached->addServer(
env('cache.memcached.host', $this->host),
env('cache.memcached.port', $this->port),
env('cache.memcached.timeout', $this->timeout)
);
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.
}
}
+348
View File
@@ -0,0 +1,348 @@
<?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\Snowflake;
use Swoole\Coroutine;
/**
* Class Redis
* @package BeReborn\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::get()->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)
{
try {
if (method_exists($this, $name)) {
$data = $this->{$name}(...$arguments);
} else {
$data = $this->proxy()->{$name}(...$arguments);
}
} catch (\Throwable $exception) {
$this->error(print_r($exception, true));
$data = false;
} finally {
return $data;
}
}
/**
* 释放连接池
*/
public function release()
{
$connections = Snowflake::get()->pool->redis;
$connections->release($this->get_config(), true);
}
/**
* 销毁连接池
*/
public function destroy()
{
$connections = Snowflake::get()->pool->redis;
$connections->destroy($this->get_config(), true);
}
/**
* @return \Redis
* @throws Exception
*/
public function proxy()
{
$connections = Snowflake::get()->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
*/
public function get_config(): array
{
return [
'host' => env('REDIS.HOST', $this->host),
'port' => env('REDIS.PORT', $this->port),
'auth' => env('REDIS.PASSWORD', $this->auth),
'timeout' => env('REDIS.TIMEOUT', 2),
'databases' => env('REDIS.DATABASE', $this->databases),
'read_timeout' => env('REDIS.READ_TIMEOUT', 10),
'prefix' => env('REDIS.PREFIX', 'system:'),
];
}
}
+139
View File
@@ -0,0 +1,139 @@
<?php
namespace Snowflake\Console;
use Exception;
use Swoole\Coroutine\Channel;
/**
* Class AbstractConsole
* @package BeReborn\Console
*/
abstract class AbstractConsole
{
/**
* @var Command[]
*/
public $commands = [];
/** @var Dtl $parameters */
private $parameters;
/** @var array */
private $_config;
/**
* @param array $config
* AbstractConsole constructor.
* @throws Exception
*/
public function __construct(array $config = [])
{
$this->_config = $config;
$this->signCommand(\BeReborn::createObject(DefaultCommand::class));
}
/**
* @return array
*/
public function getConfig()
{
return $this->_config;
}
/**
* @return $this
*/
public function setParameters()
{
$this->parameters = new Dtl($_SERVER['argv']);
return $this;
}
/**
* @param Command $command
* @return mixed
*/
public function execCommand(Command $command)
{
return $command->handler($this->parameters);
}
/**
* @return Command|null
*/
public function search()
{
$name = $this->parameters->getCommandName();
$this->parameters->set('commandList', $this->getCommandList());
foreach ($this->commands as $command) {
if ($command->command != $name) {
continue;
}
return $command;
}
return null;
}
/**
* @param Command $abstractConsole
*
* 注册命令
*/
public function signCommand(Command $abstractConsole)
{
$this->commands[] = $abstractConsole;
}
/**
* @param $kernel
* @throws Exception
*/
public function batch($kernel)
{
if (is_object($kernel)) {
if (!property_exists($kernel, 'commands')) {
return;
}
$kernel = $kernel->commands;
}
if (!is_array($kernel)) {
return;
}
foreach ($kernel as $command) {
$this->signCommand(\BeReborn::createObject($command));
}
}
/**
* @param Command $abstractConsole
* 释放一个命令
*/
public function destroyCommand(Command $abstractConsole)
{
foreach ($this->commands as $index => $command) {
if ($abstractConsole === $command) {
unset($this->commands[$index]);
break;
}
}
}
/**
* @return array
*/
private function getCommandList()
{
$_tmp = [];
foreach ($this->commands as $command) {
$_tmp[$command->command] = [$command->description, $command];
}
ksort($_tmp, SORT_ASC);
return $_tmp;
}
}
+91
View File
@@ -0,0 +1,91 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/10/7 0007
* Time: 2:16
*/
namespace BeReborn\Console;
use BeReborn\Base\BaseApplication;
use kafka\Protocol\SyncGroup;
use Swoole\Coroutine\Channel;
use Swoole\Runtime;
use Swoole\Timer;
/**
* Class Application
* @package BeReborn\Console
*/
class Application extends BaseApplication
{
/**
* @var string
*/
public $id = 'uniqueId';
private $console;
/** @var Channel */
private $channel;
/**
* Application constructor.
* @param array $config
* @throws
*/
public function __construct(array $config = [])
{
parent::__construct($config);
$this->channel = new Channel(1);
$this->console = new Console($config);
}
/**
* @param $class
* @throws
*/
public function register($class)
{
if (is_string($class) || is_callable($class, true)) {
$class = \BeReborn::createObject($class);
}
$this->console->signCommand($class);
}
/**
* @param null $kernel
* @return string|void
* @throws \Exception
*/
public function run($kernel = null)
{
setCommand(true);
try {
$params = '';
$kernel = \BeReborn::make($kernel, Kernel::class);
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
$this->console->setParameters();
$this->console->batch($kernel);
$class = $this->console->search();
$params = response()->send($this->console->execCommand($class));
} catch (\Exception $exception) {
$params = response()->send(implode("\n", [
'Msg: ' . $exception->getMessage(),
'Line: ' . $exception->getLine(),
'File: ' . $exception->getFile()
]));
} finally {
Timer::clearAll();
return $params;
}
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace Snowflake\Console;
use Snowflake\Abstracts\BaseObject;
/**
* Class Command
* @package BeReborn\Console
*/
abstract class Command extends BaseObject implements CommandInterface
{
public $command = '';
public $description = '';
/**
* @return string
* 返回执行的命令名称
*/
public function getName()
{
return $this->command;
}
/**
* @return string
*
* 返回命令描述
*/
public function getDescription()
{
return $this->description;
}
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace Snowflake\Console;
/**
* Interface CommandInterface
* @package BeReborn\Console
*/
interface CommandInterface
{
public function handler(Dtl $dtl);
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace BeReborn\Console;
/**
* Class Console
* @package BeReborn\Console
*/
class Console extends AbstractConsole
{
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace BeReborn\Console;
/**
* Class DefaultCommand
* @package BeReborn\Console
*/
class DefaultCommand extends Command
{
public $command = 'list';
public $description = 'help';
public function handler(Dtl $dtl)
{
$param = $dtl->get('commandList');
$last = '';
$lists = [str_pad('Commands', 24, ' ', STR_PAD_RIGHT) . '注释'];
foreach ($param as $key => $val) {
$split = explode(':', $key);
if (empty($last) && isset($split[0])) {
$lists[] = str_pad("\033[32;40;1;1m" . $split[0] . " \033[0m", 40, ' ', STR_PAD_RIGHT);
} else if (isset($split[0]) && $last != $split[0]) {
$lists[] = str_pad("\033[32;40;1;1m" . $split[0] . " \033[0m", 40, ' ', STR_PAD_RIGHT);
}
$last = $split[0] ?? '';
list($method, $ts) = $val;
$lists[] = str_pad("\033[32;40;1;1m " . $key . " \033[0m", 40, ' ', STR_PAD_RIGHT) . $method;
}
return implode(PHP_EOL, $lists);
}
}
+132
View File
@@ -0,0 +1,132 @@
<?php
namespace Snowflake\Console;
use HttpServer\Http\HttpParams;
use HttpServer\Http\Request;
/**
* Class Dtl
* @package BeReborn\Console
*/
class Dtl
{
private $parameters;
private $command = '';
/**
* Dtl constructor.
* @param $parameters
* @throws
*/
public function __construct($parameters)
{
$this->parameters = $this->resolve($parameters);
}
/**
* @return string
*/
public function getCommandName()
{
return $this->command;
}
/**
* @param $parameters
* @return array
* @throws \Exception
*/
public function resolve($parameters)
{
$arrays = [];
$parameters = array_slice($parameters, 1);
$this->command = array_shift($parameters);
foreach ($parameters as $parameter) {
$explode = explode('=', $parameter);
if (count($explode) < 2) {
continue;
}
$arrays[array_shift($explode)] = current($explode);
}
$request = new Request();
$request->fd = 0;
$request->params = new HttpParams([], $arrays, []);
$request->headers = new HttpParams([]);
Context::setRequest($request);
return $arrays;
}
/**
* @param $key
* @param null $default
* @return mixed|null
*/
public function get($key, $default = null)
{
return $this->parameters[$key] ?? $default;
}
/**
* @param $key
* @param $value
* @return $this
*/
public function set($key, $value)
{
$this->parameters[$key] = $value;
return $this;
}
/**
* @param array $array
* @return $this
*/
public function setBatch(array $array)
{
if (empty($array)) {
return $this;
}
foreach ($array as $key => $value) {
$this->parameters[$key] = $value;
}
return $this;
}
/**
* @return array
* 获取
*/
public function getAll()
{
return $this->parameters;
}
/**
* @return null
* 清理
*/
public function clear()
{
return $this->parameters = null;
}
/**
* @return false|string
*/
public function toJson()
{
return json_encode($this->parameters, JSON_UNESCAPED_UNICODE);
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace BeReborn\Console;
interface ICommand
{
public function handler();
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace BeReborn\Console;
class Kernel
{
public $commands = [
];
}
+99
View File
@@ -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 BeReborn\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;
}
}
+103
View File
@@ -0,0 +1,103 @@
<?php
/**
* Created by PhpStorm.
* User: dell
* Date: 2019/1/14 0014
* Time: 13:50
*/
namespace Snowflake\Core;
/**
* Class DateFormat
* @package BeReborn\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);
}
}
+182
View File
@@ -0,0 +1,182 @@
<?php
namespace Snowflake\Core;
/**
* Class Help
* @package BeReborn\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);
}
}
}
+119
View File
@@ -0,0 +1,119 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 01:04
*/
namespace Snowflake\Core;
/**
* Class JSON
* @package BeReborn\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);
}
}
+171
View File
@@ -0,0 +1,171 @@
<?php
namespace Snowflake\Core;
/**
* Class Reader
* @package BeReborn\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];
}
}
+267
View File
@@ -0,0 +1,267 @@
<?php
namespace Snowflake\Core;
use Exception;
/**
* Class Str
* @package BeReborn\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);
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 01:03
*/
namespace Snowflake\Core;
/**
* Class Xml
* @package BeReborn\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;
}
}
}
+232
View File
@@ -0,0 +1,232 @@
<?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 BeReborn\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('BeReborn\Base\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
*/
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;
}
}
+142
View File
@@ -0,0 +1,142 @@
<?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 BeReborn\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]);
}
}
}
+159
View File
@@ -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 BeReborn\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::get()->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);
Logger::error($data, 'error');
$event = Snowflake::get()->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);
Logger::trance($data, $this->category);
return print_r($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')
{
Logger::debug($message, $category);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-20
* Time: 10:25
*/
namespace Snowflake\Error;
/**
* Interface ErrorInterface
* @package BeReborn\Error
*/
interface ErrorInterface
{
/**
* @param $message
* @param $file
* @param $line
* @param int $code
* @return mixed
*/
public function sendError($message, $file, $line, $code = 500);
}
+223
View File
@@ -0,0 +1,223 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-22
* Time: 14:36
*/
namespace Snowflake\Error;
use Exception;
use Snowflake\Snowflake;
use Swoole\Coroutine\System;
use Swoole\Process;
/**
* Class Logger
* @package BeReborn\Error
*/
class Logger
{
private static $logs = [];
public static $worker_id;
/**
* @param $message
* @param string $category
* @throws Exception
*/
public static function debug($message, $category = 'app')
{
static::writer($message, $category);
}
/**
* @param $message
* @param string $category
* @throws Exception
*/
public static function trance($message, $category = 'app')
{
static::writer($message, $category);
}
/**
* @param $message
* @param string $category
* @throws Exception
*/
public static function error($message, $category = 'app')
{
static::writer($message, $category);
}
/**
* @param $message
* @param string $category
* @throws Exception
*/
public static function success($message, $category = 'app')
{
static::writer($message, $category);
}
/**
* @param $message
* @param string $category
* @return string
* @throws Exception
*/
private static function writer($message, $category = 'app')
{
if ($message instanceof \Throwable) {
$message = $message->getMessage();
} else {
if (is_array($message) || is_object($message)) {
$message = static::arrayFormat($message);
}
}
if (is_array($message)) {
$message = static::arrayFormat($message);
}
if (!empty($message)) {
if (!is_array(static::$logs)) {
static::$logs = [];
}
static::$logs[] = [$category, $message];
}
return $message;
}
/**
* @param $message
* @param $category
* @throws Exception
*/
public static function print_r($message, $category = '')
{
/** @var Process $logger */
$logger = \BeReborn::getApp('logger');
$logger->write(JSON::encode([$message, $category]));
}
/**
* @param string $application
* @return mixed
*/
public static function getLastError($application = 'app')
{
$_tmp = [];
foreach (static::$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 static 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') . ']' . $messages . PHP_EOL;
Snowflake::writeFile(storage($fileName, $dirName), $logFile, FILE_APPEND);
}
/**
* @param $logFile
* @return false|string
*/
private static 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 static function insert()
{
if (empty(static::$logs)) {
return;
}
foreach (static::$logs as $log) {
[$category, $message] = $log;
static::write($message, $category);
}
static::$logs = [];
}
/**
* @return array
*/
public static function clear()
{
return static::$logs = [];
}
/**
* @param $data
* @return string
*/
private static function arrayFormat($data)
{
if (is_string($data)) {
return $data;
}
if ($data instanceof Exception) {
$data = static::getException($data);
} else if (is_object($data)) {
$data = get_object_vars($data);
}
$_tmp = [];
foreach ($data as $key => $val) {
if (is_array($val)) {
$_tmp[] = static::arrayFormat($val);
} else {
$_tmp[] = (is_string($key) ? $key . ' : ' : '') . $val;
}
}
return implode(PHP_EOL, $_tmp);
}
/**
* @param Exception $exception
* @return array
*/
private static function getException($exception)
{
$_tmp = [$exception->getMessage()];
$_tmp[] = $exception->getFile() . ' on line ' . $exception->getLine();
$_tmp[] = $exception->getTrace();
return $_tmp;
}
}
+199
View File
@@ -0,0 +1,199 @@
<?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 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_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_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::get());
} 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;
}
/**
* @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;
}
}
+26
View File
@@ -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 BeReborn\Exception
*/
class ComponentException extends \Exception
{
public function __construct(string $message = "", int $code = 0, Throwable $previous = NULL)
{
parent::__construct($message, 5000, $previous);
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Snowflake\Exception;
class ConfigException extends \Exception
{
}
+10
View File
@@ -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 BeReborn\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);
}
}
+375
View File
@@ -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 BeReborn\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;
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace Snowflake\Pool;
use Snowflake\Snowflake;
/**
* Class Pool
* @package Snowflake\Pool
* @property $redis
* @property $db
*/
class Pool extends \Snowflake\Abstracts\Pool
{
/**
* @return RedisClient
*/
public function getRedis()
{
return Snowflake::get()->redis_connections;
}
/**
* @return Connection
*/
public function getDb()
{
return Snowflake::get()->connections;
}
}
+182
View File
@@ -0,0 +1,182 @@
<?php
namespace Snowflake\Pool;
use HttpServer\Http\Context;
use Redis;
use RedisException;
use Swoole\Coroutine;
use Exception;
/**
* Class RedisClient
* @package BeReborn\Pool
*/
class RedisClient 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 Redis
* @throws Exception
*/
private function createConnect(array $config)
{
$redis = new Redis();
if (!$redis->connect($config['host'], $config['port'], $config['timeout'])) {
throw new Exception('The Redis Connect Fail.');
}
if (empty($config['auth']) || !$redis->auth($config['auth'])) {
throw new Exception(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(Redis::OPT_READ_TIMEOUT, -1);
$redis->setOption(Redis::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 Redis)) {
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)];
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace Snowflake\Process;
interface ISystem
{
public function start();
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace Snowflake\Process;
use Exception;
use Snowflake\Snowflake;
use Swoole\Timer;
/**
* Class Logfilemonitoring
* @package components
*/
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());
});
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace Snowflake\Process;
class PrintIn extends Process
{
public function onHandler(\Swoole\Process $process)
{
do {
sleep(1);
} while (true);
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace Snowflake\Process;
use Snowflake\Abstracts\Component;
use Snowflake\Application;
/**
* Class Process
* @package BeReborn\Service
*/
abstract class Process extends Component
{
/** @var Application */
protected $application;
/**
* Process constructor.
* @param $application
* @param array $config
*/
public function __construct(Application $application, $config = [])
{
$this->application = $application;
parent::__construct([]);
}
/**
* @param \Swoole\Process $process
* @return mixed
*/
abstract public function onHandler(\Swoole\Process $process);
/**
* @param $process
*/
protected function start($process)
{
$this->onHandler($process);
}
}
+195
View File
@@ -0,0 +1,195 @@
<?php
/**
* Created by PhpStorm.
* User: admin
* Date: 2019-03-22
* Time: 19:09
*/
namespace Snowflake\Process;
use Exception;
use BeReborn;
use Snowflake\Snowflake;
use Swoole\Event;
use Swoole\Timer;
use swoole_process;
/**
* Class ServerInotify
* @package BeReborn\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 {
Timer::tick(1000, [$this, 'tick']);
}
}
public function tick()
{
}
/**
* 开始监听
*/
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->trigger_reload();
$this->clearWatch();
//重新监听
foreach ($this->dirs as $root) {
$this->watch($root);
}
$this->int = -1;
$this->isReloading = FALSE;
$this->isReloadingOut = FALSE;
}
/**
* 重启
*/
public function trigger_reload()
{
Snowflake::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;
}
}
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace Snowflake\Process;
use Snowflake\Abstracts\Component;
abstract class System extends Component implements ISystem
{
}
+13
View File
@@ -0,0 +1,13 @@
<?php
use Snowflake\Process\Leafleting;
use Snowflake\Process\ServerInotify;
return [
'processes' => [
'Leafleting' => Leafleting::class,
'inotify' => ServerInotify::class,
]
];
+119
View File
@@ -0,0 +1,119 @@
<?php
namespace Snowflake;
use Exception;
use HttpServer\ServerManager;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use Snowflake\Abstracts\Component;
use Swoole\Process;
use Swoole\Process\Pool;
use Swoole\Timer;
/**
* Class Processes
* @package Snowflake
*/
class Processes extends Component
{
public $processes = [];
/**
* 构建服务
* @throws Exception
*/
public function initCore()
{
$application = Snowflake::get();
$server = $application->set(Pool::class, new Pool($this->size(), SWOOLE_IPC_UNIXSOCK));
$server->on('workerStart', function (Pool $pool, int $workerId) use ($application) {
ServerManager::create($pool, $this->processes[$workerId], $application, $workerId);
});
$server->on('workerStop', function (Pool $pool, int $workerId) {
$event = Snowflake::get()->event;
if ($event->exists(Event::PROCESS_WORKER_STOP)) {
$event->trigger(Event::PROCESS_WORKER_STOP);
}
});
$server->on('message', function ($pool, $message) {
file_put_contents('a.log', func_get_args());
});
return $server;
}
protected function system_mail()
{
try {
$mail = new PHPMailer(true);
//Server settings
$mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'user@example.com'; // SMTP username
$mail->Password = 'secret'; // SMTP password
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
//Recipients
$mail->setFrom('from@example.com', 'Mailer');
$mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient
$mail->addAddress('ellen@example.com'); // Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');
// Attachments
$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Here is the subject';
$mail->Body = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}
/**
* @return int
*/
protected function size()
{
return count($this->processes);
}
/**
* @throws Exception
*/
public function start()
{
$server = $this->initCore();
$server->start();
}
/**
* @param array $servers
* @return $this
*/
public function push(array $servers)
{
foreach ($servers as $server) {
$this->processes[] = $server;
}
return $this;
}
}
+191
View File
@@ -0,0 +1,191 @@
<?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 get()
{
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;
}
/**
* @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 int $is_append
* @return false|int|mixed
*/
public static function writeFile($fileName, $content, $is_append = FILE_APPEND)
{
return false;
// if (self::inCoroutine()) {
// return Coroutine::writeFile($fileName, $content, $is_append);
// } else {
// return file_put_contents($fileName, $content, $is_append);
// }
}
/**
* @param $object
* @param $config
* @return mixed
*/
public static function configure($object, $config)
{
foreach ($config as $key => $value) {
$object->$key = $value;
}
return $object;
}
public static function clearProcessId($worker_pid)
{
}
/**
* @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();