2020-03-02 16:14:20 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Framework;
|
|
|
|
|
|
|
2020-07-11 15:53:30 +08:00
|
|
|
|
use Doctrine\Common\Annotations\AnnotationReader;
|
|
|
|
|
|
use ReflectionClass;
|
|
|
|
|
|
use ReflectionMethod;
|
2020-04-14 23:46:42 +08:00
|
|
|
|
use Swoole\Runtime;
|
2020-07-11 15:53:30 +08:00
|
|
|
|
use ZM\Annotation\Swoole\OnEvent;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
use Exception;
|
|
|
|
|
|
use Swoole\WebSocket\Server;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Class FrameworkLoader
|
|
|
|
|
|
* Everything is beginning from here
|
|
|
|
|
|
* @package Framework
|
|
|
|
|
|
*/
|
|
|
|
|
|
class FrameworkLoader
|
|
|
|
|
|
{
|
|
|
|
|
|
/** @var GlobalConfig */
|
|
|
|
|
|
public static $settings;
|
|
|
|
|
|
|
|
|
|
|
|
/** @var FrameworkLoader|null */
|
|
|
|
|
|
public static $instance = null;
|
|
|
|
|
|
|
|
|
|
|
|
/** @var float|string */
|
|
|
|
|
|
public static $run_time;
|
2020-03-05 14:38:12 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @var array
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static $argv;
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
|
|
|
|
|
/** @var Server */
|
|
|
|
|
|
private $server;
|
|
|
|
|
|
|
2020-05-02 23:27:26 +08:00
|
|
|
|
public function __construct($args = []) {
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$this->requireGlobalFunctions();
|
2020-06-05 13:36:30 +08:00
|
|
|
|
if (LOAD_MODE == 0) define("WORKING_DIR", getcwd());
|
2020-06-13 11:28:31 +08:00
|
|
|
|
elseif (LOAD_MODE == 1) define("WORKING_DIR", realpath(__DIR__ . "/../../"));
|
2020-06-05 13:36:30 +08:00
|
|
|
|
elseif (LOAD_MODE == 2) echo "Phar mode: " . WORKING_DIR . PHP_EOL;
|
2020-06-13 11:28:31 +08:00
|
|
|
|
//$this->registerAutoloader('classLoader');
|
|
|
|
|
|
require_once "DataProvider.php";
|
|
|
|
|
|
if (file_exists(DataProvider::getWorkingDir() . "/vendor/autoload.php")) {
|
2020-07-11 15:53:30 +08:00
|
|
|
|
/** @noinspection PhpIncludeInspection */
|
2020-06-13 11:28:31 +08:00
|
|
|
|
require_once DataProvider::getWorkingDir() . "/vendor/autoload.php";
|
|
|
|
|
|
}
|
|
|
|
|
|
if (LOAD_MODE == 2) {
|
|
|
|
|
|
require_once FRAMEWORK_DIR . "/vendor/autoload.php";
|
|
|
|
|
|
spl_autoload_register('phar_classloader');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-05-23 17:23:29 +08:00
|
|
|
|
self::$settings = new GlobalConfig();
|
|
|
|
|
|
if (self::$settings->get("debug_mode") === true) {
|
|
|
|
|
|
$args[] = "--debug-mode";
|
|
|
|
|
|
$args[] = "--disable-console-input";
|
|
|
|
|
|
}
|
|
|
|
|
|
self::$argv = $args;
|
|
|
|
|
|
if (!in_array("--debug-mode", self::$argv)) {
|
|
|
|
|
|
Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL);
|
|
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
self::$settings = new GlobalConfig();
|
|
|
|
|
|
ZMBuf::$globals = self::$settings;
|
|
|
|
|
|
if (!self::$settings->success) die("Failed to load global config. Please check config/global.php file");
|
|
|
|
|
|
$this->defineProperties();
|
|
|
|
|
|
|
|
|
|
|
|
//start swoole Framework
|
|
|
|
|
|
$this->selfCheck();
|
|
|
|
|
|
try {
|
|
|
|
|
|
$this->server = new Server(self::$settings->get("host"), self::$settings->get("port"));
|
2020-04-29 15:29:56 +08:00
|
|
|
|
$settings = self::$settings->get("swoole");
|
|
|
|
|
|
if (in_array("--daemon", $args)) {
|
|
|
|
|
|
$settings["daemonize"] = 1;
|
|
|
|
|
|
Console::log("已启用守护进程,输出重定向到 " . $settings["log_file"]);
|
|
|
|
|
|
self::$argv[] = "--disable-console-input";
|
|
|
|
|
|
}
|
|
|
|
|
|
$this->server->set($settings);
|
2020-07-11 15:53:30 +08:00
|
|
|
|
$all_event_class = self::$settings->get("server_event_handler_class");
|
|
|
|
|
|
$event_list = [];
|
|
|
|
|
|
foreach ($all_event_class as $v) {
|
|
|
|
|
|
$reader = new AnnotationReader();
|
|
|
|
|
|
$reflection_class = new ReflectionClass($v);
|
|
|
|
|
|
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
|
|
|
|
|
|
foreach ($methods as $vs) {
|
|
|
|
|
|
$method_annotations = $reader->getMethodAnnotations($vs);
|
|
|
|
|
|
if ($method_annotations != []) {
|
|
|
|
|
|
$annotation = $method_annotations[0];
|
|
|
|
|
|
if ($annotation instanceof OnEvent) {
|
|
|
|
|
|
$annotation->class = $v;
|
|
|
|
|
|
$annotation->method = $vs->getName();
|
|
|
|
|
|
$event_list[strtolower($annotation->event)] = $annotation;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach ($event_list as $k => $v) {
|
|
|
|
|
|
$this->server->on($k, function (...$param) use ($v) {
|
|
|
|
|
|
$c = $v->class;
|
|
|
|
|
|
//echo $c.PHP_EOL;
|
|
|
|
|
|
$c = new $c();
|
|
|
|
|
|
call_user_func_array([$c, $v->method], $param);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-02 16:14:20 +08:00
|
|
|
|
ZMBuf::initAtomic();
|
2020-06-05 13:36:30 +08:00
|
|
|
|
if (in_array("--remote-shell", $args)) RemoteShell::listen($this->server, "127.0.0.1");
|
2020-04-29 15:29:56 +08:00
|
|
|
|
if (in_array("--log-error", $args)) ZMBuf::$atomics["info_level"]->set(0);
|
|
|
|
|
|
if (in_array("--log-warning", $args)) ZMBuf::$atomics["info_level"]->set(1);
|
|
|
|
|
|
if (in_array("--log-info", $args)) ZMBuf::$atomics["info_level"]->set(2);
|
|
|
|
|
|
if (in_array("--log-verbose", $args)) ZMBuf::$atomics["info_level"]->set(3);
|
|
|
|
|
|
if (in_array("--log-debug", $args)) ZMBuf::$atomics["info_level"]->set(4);
|
2020-04-29 15:38:57 +08:00
|
|
|
|
Console::log(
|
|
|
|
|
|
"host: " . self::$settings->get("host") .
|
|
|
|
|
|
", port: " . self::$settings->get("port") .
|
|
|
|
|
|
", log_level: " . ZMBuf::$atomics["info_level"]->get() .
|
2020-06-08 23:52:55 +08:00
|
|
|
|
", version: " . ZM_VERSION .
|
2020-06-05 13:36:30 +08:00
|
|
|
|
"\nworking_dir: " . DataProvider::getWorkingDir()
|
2020-04-29 15:38:57 +08:00
|
|
|
|
);
|
|
|
|
|
|
global $motd;
|
2020-05-23 17:23:29 +08:00
|
|
|
|
if (!file_exists(DataProvider::getWorkingDir() . "/config/motd.txt")) {
|
|
|
|
|
|
echo $motd;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
echo file_get_contents(DataProvider::getWorkingDir() . "/config/motd.txt");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (in_array("--debug-mode", self::$argv))
|
|
|
|
|
|
Console::warning("You are in debug mode, do not use in production!");
|
2020-07-11 15:53:30 +08:00
|
|
|
|
register_shutdown_function(function() {
|
|
|
|
|
|
$error = error_get_last();
|
|
|
|
|
|
if(isset($error["type"]) && $error["type"] == 1) {
|
|
|
|
|
|
if(mb_strpos($error["message"], "require") !== false && mb_strpos($error["message"], "callback") !== false) {
|
|
|
|
|
|
echo "\e[38;5;203mYou may need to update your \"global.php\" config!\n";
|
|
|
|
|
|
echo "Please see: https://github.com/zhamao-robot/zhamao-framework/issues/15\e[m\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2020-03-02 16:14:20 +08:00
|
|
|
|
$this->server->start();
|
|
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
Console::error("Framework初始化出现错误,请检查!");
|
|
|
|
|
|
Console::error($e->getMessage());
|
|
|
|
|
|
die;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-02 23:27:26 +08:00
|
|
|
|
private function requireGlobalFunctions() {
|
|
|
|
|
|
require_once __DIR__ . '/global_functions.php';
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-02 23:27:26 +08:00
|
|
|
|
private function defineProperties() {
|
2020-03-02 16:14:20 +08:00
|
|
|
|
define("ZM_START_TIME", microtime(true));
|
|
|
|
|
|
define("ZM_DATA", self::$settings->get("zm_data"));
|
2020-06-13 11:28:31 +08:00
|
|
|
|
define("ZM_VERSION", json_decode(file_get_contents(__DIR__ . "/../../composer.json"), true)["version"] ?? "unknown");
|
2020-03-02 16:14:20 +08:00
|
|
|
|
define("CONFIG_DIR", self::$settings->get("config_dir"));
|
|
|
|
|
|
define("CRASH_DIR", self::$settings->get("crash_dir"));
|
|
|
|
|
|
@mkdir(ZM_DATA);
|
|
|
|
|
|
@mkdir(CONFIG_DIR);
|
|
|
|
|
|
@mkdir(CRASH_DIR);
|
|
|
|
|
|
define("ZM_MATCH_ALL", 0);
|
|
|
|
|
|
define("ZM_MATCH_FIRST", 1);
|
|
|
|
|
|
define("ZM_MATCH_NUMBER", 2);
|
|
|
|
|
|
define("ZM_MATCH_SECOND", 3);
|
2020-05-23 17:23:29 +08:00
|
|
|
|
define("ZM_BREAKPOINT", 'if(in_array("--debug-mode", \Framework\FrameworkLoader::$argv)) extract(\Psy\debug(get_defined_vars(), isset($this) ? $this : @get_called_class()));');
|
2020-06-20 14:51:24 +08:00
|
|
|
|
define("BP", ZM_BREAKPOINT);
|
2020-06-15 19:50:07 +08:00
|
|
|
|
define("ZM_DEFAULT_FETCH_MODE", self::$settings->get("sql_config")["sql_default_fetch_mode"] ?? 4);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-05-02 23:27:26 +08:00
|
|
|
|
private function selfCheck() {
|
2020-03-02 16:14:20 +08:00
|
|
|
|
if (!extension_loaded("swoole")) die("Can not find swoole extension.\n");
|
2020-05-23 17:23:29 +08:00
|
|
|
|
if (version_compare(SWOOLE_VERSION, "4.4.13") == -1) die("You must install swoole version >= 4.4.13 !");
|
2020-03-02 16:14:20 +08:00
|
|
|
|
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
|
|
|
|
|
|
if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
2020-05-23 17:23:29 +08:00
|
|
|
|
if (!extension_loaded("ctype")) die("Can not find ctype extension.\n");
|
2020-03-02 16:14:20 +08:00
|
|
|
|
if (!function_exists("mb_substr")) die("Can not find mbstring extension.\n");
|
|
|
|
|
|
if (substr(PHP_VERSION, 0, 1) != "7") die("PHP >=7 required.\n");
|
|
|
|
|
|
//if (!function_exists("curl_exec")) die("Can not find curl extension.\n");
|
|
|
|
|
|
//if (!class_exists("ZipArchive")) die("Can not find Zip extension.\n");
|
|
|
|
|
|
//if (!file_exists(CRASH_DIR . "last_error.log")) die("Can not find log file.\n");
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-04-14 23:46:42 +08:00
|
|
|
|
}
|
2020-04-29 15:38:57 +08:00
|
|
|
|
|
|
|
|
|
|
global $motd;
|
|
|
|
|
|
$motd = <<<EOL
|
|
|
|
|
|
______
|
|
|
|
|
|
|__ / |__ __ _ _ __ ___ __ _ ___
|
|
|
|
|
|
/ /| '_ \ / _` | '_ ` _ \ / _` |/ _ \
|
|
|
|
|
|
/ /_| | | | (_| | | | | | | (_| | (_) |
|
|
|
|
|
|
/____|_| |_|\__,_|_| |_| |_|\__,_|\___/
|
|
|
|
|
|
|
2020-05-23 17:23:29 +08:00
|
|
|
|
|
2020-04-29 15:38:57 +08:00
|
|
|
|
EOL;
|
|
|
|
|
|
|