update to 1.2.1

add phar build script
This commit is contained in:
whale 2020-05-02 23:27:26 +08:00
parent 97e579b8a1
commit 82a1f86bbd
19 changed files with 292 additions and 119 deletions

3
.gitignore vendored
View File

@ -4,4 +4,5 @@
/vendor/
zm.json
/zm_data/
composer.lock
composer.lock
/resources/server.phar

64
bin/phar-build Executable file

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
"description": "high-performance intelligent assistant",
"minimum-stability": "stable",
"license": "proprietary",
"version": "1.2.0",
"version": "1.2.1",
"authors": [
{
"name": "whale",
@ -22,7 +22,8 @@
"ext-json": "*",
"ext-posix": "*",
"ext-ctype": "*",
"ext-pcntl": "*"
"ext-pcntl": "*",
"nikic/php-parser": "^4.4"
},
"repositories": {
"packagist": {

82
phar-starter.php Normal file
View File

@ -0,0 +1,82 @@
<?php
global $is_phar;
use Framework\FrameworkLoader;
$is_phar = true;
if (substr(__DIR__, 0, 7) != 'phar://') {
die("You can not run this script directly!\n");
}
testEnvironment();
spl_autoload_register(function ($class) {
//echo $class."\n";
$exp = str_replace("\\", '/', $class);
$exp = __DIR__ . '/src/' . $exp . '.php';
if (is_file($exp)) {
require_once $exp;
}
});
loadPhp(__DIR__ . '/src');
Swoole\Coroutine::set([
'max_coroutine' => 30000,
]);
date_default_timezone_set("Asia/Shanghai");
define('WORKING_DIR', __DIR__);
$s = new FrameworkLoader($argv);
function loadPhp($dir) {
$dirs = scandir($dir);
foreach ($dirs as $v) {
$path = $dir . '/' . $v;
if (is_dir($path)) {
loadPhp($path);
} else {
if (pathinfo($dir . '/' . $v)['extension'] == 'php') {
//echo 'loading '.$path.PHP_EOL;
require_once $path;
}
}
}
}
function testEnvironment() {
$current_dir = realpath('.');
@mkdir($current_dir . '/config/');
if (!is_file($current_dir . '/config/global.php')) {
echo "Exporting default global config...\n";
$global = file_get_contents(__DIR__ . '/config/global.php');
$global = str_replace("WORKING_DIR", 'realpath("../")', $global);
file_put_contents($current_dir . '/config/global.php', $global);
}
if (!is_file($current_dir . '/config/file_header.json')) {
echo "Exporting default file_header config...\n";
$global = file_get_contents(__DIR__ . '/config/file_header.json');
file_put_contents($current_dir . '/config/file_header.json', $global);
}
if (!is_dir($current_dir . '/resources')) mkdir($current_dir . '/resources');
if (!is_dir($current_dir . '/src')) mkdir($current_dir . '/src');
if (!is_dir($current_dir . '/src')) mkdir($current_dir . '/src');
if (!is_dir($current_dir . '/src/Module')) {
mkdir($current_dir . '/src/Module');
mkdir($current_dir . '/src/Module/Example');
file_put_contents($current_dir . '/src/Module/Example/Hello.php', file_get_contents(__DIR__ . '/tmp/Hello.php.bak'));
mkdir($current_dir . '/src/Module/Middleware');
file_put_contents($current_dir . '/src/Module/Middleware/TimerMiddleware.php', file_get_contents(__DIR__ . '/tmp/TimerMiddleware.php.bak'));
}
if (!is_dir($current_dir . '/src/Custom')) {
mkdir($current_dir . '/src/Custom');
mkdir($current_dir . '/src/Custom/Annotation');
mkdir($current_dir . '/src/Custom/Connection');
file_put_contents($current_dir . '/src/Custom/global_function.php', "<?php\n\n//这里写你的全局方法");
}
}

View File

@ -207,6 +207,12 @@ class Console
case 'r':
ZMUtil::reload();
return false;
case 'save':
$origin = ZMBuf::$atomics["info_level"]->get();
ZMBuf::$atomics["info_level"]->set(3);
DataProvider::saveBuffer();
ZMBuf::$atomics["info_level"]->set($origin);
return true;
case '':
return true;
default:

View File

@ -0,0 +1,63 @@
<?php
namespace Framework;
class DataProvider
{
public static $buffer_list = [];
public static function getResourceFolder() {
return self::getWorkingDir() . '/resources/';
}
public static function getWorkingDir() {
global $is_phar;
if($is_phar === true) {
return realpath('.');
} else {
return WORKING_DIR;
}
}
public static function getDataConfig() {
return CONFIG_DIR;
}
public static function addSaveBuffer($buf_name, $sub_folder = null) {
$name = ($sub_folder ?? "") . "/" . $buf_name . ".json";
self::$buffer_list[$buf_name] = $name;
Console::debug("Added ".$buf_name . " at $sub_folder");
ZMBuf::set($buf_name, self::getJsonData($name));
}
public static function saveBuffer() {
$head = Console::setColor(date("[H:i:s] ") . "[V] Saving buffer......", "blue");
if (ZMBuf::$atomics["info_level"]->get() >= 3)
echo $head;
foreach (self::$buffer_list as $k => $v) {
self::setJsonData($v, ZMBuf::get($k));
}
if (ZMBuf::$atomics["info_level"]->get() >= 3)
echo Console::setColor("saved", "blue") . PHP_EOL;
}
public static function getFrameworkLink() {
return ZMBuf::globals("http_reverse_link");
}
public static function getJsonData(string $string) {
if (!file_exists(self::getDataConfig() . $string)) return [];
return json_decode(file_get_contents(self::getDataConfig() . $string), true);
}
private static function setJsonData($filename, array $args) {
Console::debug("Saving ".$filename);
file_put_contents(self::getDataConfig() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
}
public static function getDataFolder() {
return ZM_DATA;
}
}

View File

@ -35,17 +35,20 @@ class FrameworkLoader
/** @var Server */
private $server;
public function __construct($args = [])
{
public function __construct($args = []) {
if (self::$instance !== null) die("Cannot run two FrameworkLoader in one process!");
self::$instance = $this;
self::$argv = $args;
chdir(__DIR__ . '/../..');
define('WORKING_DIR', getcwd());
Runtime::enableCoroutine();
$this->requireGlobalFunctions();
if (!isPharMode()) {
define('WORKING_DIR', getcwd());
} else {
echo "Phar mode: " . WORKING_DIR . PHP_EOL;
}
$this->registerAutoloader('classLoader');
Runtime::enableCoroutine();
self::$settings = new GlobalConfig();
ZMBuf::$globals = self::$settings;
if (!self::$settings->success) die("Failed to load global config. Please check config/global.php file");
@ -91,7 +94,8 @@ class FrameworkLoader
"host: " . self::$settings->get("host") .
", port: " . self::$settings->get("port") .
", log_level: " . ZMBuf::$atomics["info_level"]->get() .
", version: " . json_decode(file_get_contents(WORKING_DIR . "/composer.json"), true)["version"]
", version: " . json_decode(file_get_contents(WORKING_DIR . "/composer.json"), true)["version"] .
"\nworking_dir: ".(isPharMode() ? realpath('.') : WORKING_DIR)
);
global $motd;
echo $motd . PHP_EOL;
@ -103,18 +107,15 @@ class FrameworkLoader
}
}
private function requireGlobalFunctions()
{
require __DIR__ . '/global_functions.php';
private function requireGlobalFunctions() {
require_once __DIR__ . '/global_functions.php';
}
private function registerAutoloader(string $string)
{
private function registerAutoloader(string $string) {
if (!spl_autoload_register($string)) die("Failed to register autoloader named \"$string\" !");
}
private function defineProperties()
{
private function defineProperties() {
define("ZM_START_TIME", microtime(true));
define("ZM_DATA", self::$settings->get("zm_data"));
define("CONFIG_DIR", self::$settings->get("config_dir"));
@ -128,8 +129,7 @@ class FrameworkLoader
define("ZM_MATCH_SECOND", 3);
}
private function selfCheck()
{
private function selfCheck() {
if (!extension_loaded("swoole")) die("Can not find swoole extension.\n");
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
@ -141,8 +141,7 @@ class FrameworkLoader
return true;
}
public function onWorkerStart(\Swoole\Server $server, $worker_id)
{
public function onWorkerStart(\Swoole\Server $server, $worker_id) {
self::$instance = $this;
self::$run_time = microtime(true);
EventHandler::callSwooleEvent("WorkerStart", $server, $worker_id);

View File

@ -18,7 +18,8 @@ class GlobalConfig
public $success = false;
public function __construct() {
include_once WORKING_DIR . '/config/global.php';
/** @noinspection PhpIncludeInspection */
include_once DataProvider::getWorkingDir() . '/config/global.php';
global $config;
$this->success = true;
$this->config = $config;

View File

@ -1,9 +1,14 @@
<?php
use Framework\Console;
use Framework\DataProvider;
use Framework\ZMBuf;
use ZM\Context\ContextInterface;
function isPharMode(){
return substr(__DIR__, 0, 7) == 'phar://';
}
function classLoader($p) {
$filepath = getClassPath($p);
if ($filepath === null)
@ -19,11 +24,16 @@ function classLoader($p) {
function getClassPath($class_name) {
$dir = str_replace("\\", "/", $class_name);
$dir = WORKING_DIR . "/src/" . $dir . ".php";
//echo "@@@".$dir.PHP_EOL;
$dir = str_replace("\\", "/", $dir);
if (file_exists($dir)) return $dir;
else return null;
$dir2 = WORKING_DIR . "/src/" . $dir . ".php";
//echo "@@@".$dir2.PHP_EOL;
$dir2 = str_replace("\\", "/", $dir2);
if (file_exists($dir2)) return $dir2;
else {
$dir = DataProvider::getWorkingDir() . "/src/" . $dir . ".php";
//echo "###".$dir.PHP_EOL;
if (file_exists($dir)) return $dir;
else return null;
}
}
/**

View File

@ -24,14 +24,15 @@ class Hello extends ModBase
* @SwooleEventAt("open",rule="connectType:qq")
* @param $conn
*/
public function onConnect(CQConnection $conn){
Console::info("机器人 ".$conn->getQQ()." 已连接!");
public function onConnect(CQConnection $conn) {
Console::info("机器人 " . $conn->getQQ() . " 已连接!");
}
/**
* 向机器人发送"你好",即可回复这句话
* @CQCommand("你好")
*/
public function hello(){
public function hello() {
return "你好啊,我是由炸毛框架构建的机器人!";
}
@ -40,7 +41,7 @@ class Hello extends ModBase
* @RequestMapping("/httpTimer")
* @Middleware("timer")
*/
public function timer(){
public function timer() {
return "This page is used as testing TimerMiddleware! Do not use it in production.";
}
@ -48,7 +49,7 @@ class Hello extends ModBase
* 框架会默认关闭未知的WebSocket链接因为这个绑定的事件你可以根据你自己的需求进行修改
* @SwooleEventAt(type="open",rule="connectType:unknown")
*/
public function closeUnknownConn(){
public function closeUnknownConn() {
Console::info("Unknown connection , I will close it.");
$this->connection->close();
}

View File

@ -18,7 +18,7 @@ use ZM\Annotation\Swoole\{OnStart, OnTick, SwooleEventAfter, SwooleEventAt};
use ZM\Annotation\Interfaces\Rule;
use ZM\Connection\WSConnection;
use ZM\Http\MiddlewareInterface;
use ZM\Utils\DataProvider;
use Framework\DataProvider;
use ZM\Utils\ZMUtil;
class AnnotationParser
@ -30,7 +30,7 @@ class AnnotationParser
*/
public static function registerMods() {
self::loadAnnotationClasses();
$all_class = getAllClasses(WORKING_DIR . "/src/Module/", "Module");
$all_class = getAllClasses(DataProvider::getWorkingDir() . "/src/Module/", "Module");
ZMBuf::$req_mapping[0] = [
'id' => 0,
'pid' => -1,
@ -38,6 +38,7 @@ class AnnotationParser
];
$reader = new AnnotationReader();
foreach ($all_class as $v) {
Console::debug("正在检索 ".$v);
$reflection_class = new ReflectionClass($v);
$class_prefix = '';
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
@ -47,15 +48,15 @@ class AnnotationParser
if ($vs instanceof Closed) {
continue 2;
} elseif ($vs instanceof Controller) {
Console::debug("找到 Controller 中间件: ".$vs->class);
Console::debug("找到 Controller 中间件: " . $vs->class);
$class_prefix = $vs->prefix;
} elseif ($vs instanceof SaveBuffer) {
Console::debug("注册自动保存的缓存变量: ".$vs->buf_name." (Dir:".$vs->sub_folder.")");
Console::debug("注册自动保存的缓存变量: " . $vs->buf_name . " (Dir:" . $vs->sub_folder . ")");
DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder);
} elseif ($vs instanceof InitBuffer) {
ZMBuf::set($vs->buf_name, []);
} elseif ($vs instanceof MiddlewareClass) {
Console::verbose("正在注册中间件 " . $vs->class);
Console::verbose("正在注册中间件 " . $reflection_class->getName());
$result = [
"class" => "\\" . $reflection_class->getName()
];
@ -299,9 +300,9 @@ class AnnotationParser
$s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php";
require_once $s;
}
$class = getAllClasses(WORKING_DIR . "/src/Custom/Annotation/", "Custom\\Annotation");
$class = getAllClasses(DataProvider::getWorkingDir() . "/src/Custom/Annotation/", "Custom\\Annotation");
foreach ($class as $v) {
$s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php";
$s = DataProvider::getWorkingDir() . '/src/' . str_replace("\\", "/", $v) . ".php";
require_once $s;
}
}

View File

@ -20,4 +20,4 @@ class CQConnection extends WSConnection
public function getType() {
return "qq";
}
}
}

View File

@ -5,6 +5,7 @@ namespace ZM\Connection;
use Framework\ZMBuf;
use Framework\DataProvider;
class ConnectionManager
{
@ -67,7 +68,7 @@ class ConnectionManager
}
public static function registerCustomClass() {
$classes = getAllClasses(WORKING_DIR . "/src/Custom/Connection/", "Custom\\Connection");
$classes = getAllClasses(DataProvider::getWorkingDir(). "/src/Custom/Connection/", "Custom\\Connection");
ZMBuf::$custom_connection_class = $classes;
}
}

View File

@ -91,6 +91,7 @@ class DB
if (ZMBuf::get("sql_log") === true) {
$starttime = microtime(true);
}
Console::debug("MySQL: ".$line);
try {
$conn = ZMBuf::$sql_pool->get();
if ($conn === false) {

View File

@ -11,7 +11,7 @@ use Framework\Console;
use Framework\ZMBuf;
use ZM\Event\Swoole\{MessageEvent, RequestEvent, WorkerStartEvent, WSCloseEvent, WSOpenEvent};
use ZM\Http\Response;
use ZM\Utils\DataProvider;
use Framework\DataProvider;
use ZM\Utils\ZMUtil;
class EventHandler

View File

@ -17,6 +17,7 @@ use ZM\Http\MiddlewareInterface;
use ZM\Http\Response;
use ZM\ModBase;
use ZM\ModHandleType;
use Framework\DataProvider;
use ZM\Utils\ZMUtil;
class RequestEvent implements SwooleEvent
@ -90,7 +91,7 @@ class RequestEvent implements SwooleEvent
$path = realpath($base_dir . urldecode($uri));
if ($path !== false) {
if (is_dir($path)) $path = $path . '/';
$work = realpath(WORKING_DIR) . '/';
$work = realpath(DataProvider::getWorkingDir()) . '/';
if (strpos($path, $work) !== 0) {
$this->responseStatus(403);
return $this;

View File

@ -25,7 +25,7 @@ use Swoole\Server;
use ZM\Exception\DbException;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\DataProvider;
use Framework\DataProvider;
use ZM\Utils\SQLPool;
use ZM\Utils\ZMUtil;
@ -50,7 +50,7 @@ class WorkerStartEvent implements SwooleEvent
*/
public function onActivate(): WorkerStartEvent {
Console::info("Worker启动中");
Process::signal(SIGINT, function (){
Process::signal(SIGINT, function () {
Console::warning("Server interrupted by keyboard.");
ZMUtil::stop(true);
});
@ -61,16 +61,16 @@ class WorkerStartEvent implements SwooleEvent
//设置炸毛buf中储存的对象
ZMBuf::$globals = new GlobalConfig();
ZMBuf::$config = [];
$file = scandir(WORKING_DIR . '/config/');
$file = scandir(DataProvider::getWorkingDir() . '/config/');
unset($file[0], $file[1]);
foreach ($file as $k => $v) {
if ($v == "global.php") continue;
$name = explode(".", $v);
if (($prefix = end($name)) == "json") {
ZMBuf::$config[$name[0]] = json_decode(Co::readFile(WORKING_DIR . '/config/' . $v), true);
ZMBuf::$config[$name[0]] = json_decode(Co::readFile(DataProvider::getWorkingDir() . '/config/' . $v), true);
Console::info("已读取配置文件:" . $v);
} elseif ($prefix == "php") {
ZMBuf::$config[$name[0]] = include_once WORKING_DIR . '/config/' . $v;
ZMBuf::$config[$name[0]] = include_once DataProvider::getWorkingDir() . '/config/' . $v;
if (is_array(ZMBuf::$config[$name[0]]))
Console::info("已读取配置文件:" . $v);
}
@ -98,7 +98,7 @@ class WorkerStartEvent implements SwooleEvent
Coroutine::resume($v);
}
ZMBuf::unsetCache("wait_start");
foreach(ZMBuf::$events[OnStart::class] ?? [] as $v) {
foreach (ZMBuf::$events[OnStart::class] ?? [] as $v) {
$class_name = $v->class;
/** @var ModBase $class */
$class = new $class_name(["server" => $this->server, "worker_id" => $this->worker_id], ModHandleType::SWOOLE_WORKER_START);
@ -136,7 +136,7 @@ class WorkerStartEvent implements SwooleEvent
private function loadAllClass() {
//加载phar包
Console::info("加载外部phar包中");
$dir = WORKING_DIR . "/resources/package/";
$dir = DataProvider::getWorkingDir() . "/resources/package/";
if (is_dir($dir)) {
$list = scandir($dir);
unset($list[0], $list[1]);
@ -147,8 +147,12 @@ class WorkerStartEvent implements SwooleEvent
}
//加载composer类
Console::info("加载composer资源中");
require_once WORKING_DIR . "/vendor/autoload.php";
if (file_exists(DataProvider::getWorkingDir() . "/vendor/autoload.php")) {
Console::info("加载composer资源中");
require_once DataProvider::getWorkingDir() . "/vendor/autoload.php";
} else {
if(isPharMode()) require_once WORKING_DIR . "/vendor/autoload.php";
}
//加载各个模块的注解类,以及反射
Console::info("检索Module中");
@ -158,8 +162,8 @@ class WorkerStartEvent implements SwooleEvent
ConnectionManager::registerCustomClass();
//加载自定义的全局函数
if(file_exists(WORKING_DIR."/src/Custom/global_function.php"))
require_once WORKING_DIR."/src/Custom/global_function.php";
if (file_exists(DataProvider::getWorkingDir() . "/src/Custom/global_function.php"))
require_once DataProvider::getWorkingDir() . "/src/Custom/global_function.php";
$this->afterCheck();
}
@ -175,7 +179,7 @@ class WorkerStartEvent implements SwooleEvent
*/
private function afterCheck() {
$context_class = ZMBuf::globals("context_class");
if(!is_a($context_class, ContextInterface::class, true)) {
if (!is_a($context_class, ContextInterface::class, true)) {
throw new Exception("Context class must implemented from ContextInterface!");
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace ZM\Utils;
use Co;
use Framework\Console;
use Framework\ZMBuf;
class DataProvider
{
public static $buffer_list = [];
public static function getResourceFolder()
{
return WORKING_DIR . '/resources/';
}
public static function getDataConfig()
{
return CONFIG_DIR;
}
public static function addSaveBuffer($buf_name, $sub_folder = null)
{
$name = ($sub_folder ?? "") . "/" . $buf_name . ".json";
self::$buffer_list[$buf_name] = $name;
ZMBuf::set($buf_name, self::getJsonData($name));
}
public static function saveBuffer()
{
$head = Console::setColor(date("[H:i:s] ") . "[V] Saving buffer......", "blue");
if (ZMBuf::$atomics["info_level"]->get() >= 3)
echo $head;
foreach (self::$buffer_list as $k => $v) {
self::setJsonData($v, ZMBuf::get($k));
}
if (ZMBuf::$atomics["info_level"]->get() >= 3)
echo Console::setColor("saved", "blue") . PHP_EOL;
}
public static function getFrameworkLink()
{
return ZMBuf::globals("http_reverse_link");
}
public static function getJsonData(string $string)
{
if (!file_exists(self::getDataConfig() . $string)) return [];
return json_decode(Co::readFile(self::getDataConfig() . $string), true);
}
private static function setJsonData($filename, array $args)
{
Co::writeFile(self::getDataConfig() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
}
public static function getDataFolder()
{
return ZM_DATA;
}
}

View File

@ -6,6 +6,7 @@ namespace ZM\Utils;
use Co;
use framework\Console;
use Framework\DataProvider;
use Framework\ZMBuf;
class ZMUtil