2020-08-31 10:11:06 +08:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace ZM;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use Doctrine\Common\Annotations\AnnotationReader;
|
|
|
|
|
|
use Exception;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
use ZM\Annotation\Swoole\OnSetup;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Config\ZMConfig;
|
|
|
|
|
|
use ZM\ConnectionManager\ManagerGM;
|
2021-03-02 21:24:31 +08:00
|
|
|
|
use ZM\Console\TermColor;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Event\ServerEventHandler;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Store\LightCache;
|
2020-11-03 21:02:24 +08:00
|
|
|
|
use ZM\Store\LightCacheInside;
|
|
|
|
|
|
use ZM\Store\Lock\SpinLock;
|
|
|
|
|
|
use ZM\Store\ZMAtomic;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Utils\DataProvider;
|
|
|
|
|
|
use ReflectionClass;
|
|
|
|
|
|
use ReflectionException;
|
|
|
|
|
|
use ReflectionMethod;
|
|
|
|
|
|
use Swoole\Runtime;
|
|
|
|
|
|
use Swoole\WebSocket\Server;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
use ZM\Annotation\Swoole\SwooleHandler;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Console\Console;
|
2020-09-29 15:07:43 +08:00
|
|
|
|
use ZM\Utils\ZMUtil;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
|
|
|
|
|
class Framework
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @var array
|
|
|
|
|
|
*/
|
2020-09-29 15:07:43 +08:00
|
|
|
|
public static $argv;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @var Server
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static $server;
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @var array|bool|mixed|null
|
|
|
|
|
|
*/
|
|
|
|
|
|
private $server_set;
|
|
|
|
|
|
|
|
|
|
|
|
public function __construct($args = []) {
|
|
|
|
|
|
$tty_width = $this->getTtyWidth();
|
|
|
|
|
|
|
|
|
|
|
|
self::$argv = $args;
|
|
|
|
|
|
|
2020-12-20 18:49:03 +08:00
|
|
|
|
ZMConfig::setDirectory(DataProvider::getWorkingDir() . '/config');
|
|
|
|
|
|
ZMConfig::setEnv($args["env"] ?? "");
|
|
|
|
|
|
if (ZMConfig::get("global") === false) {
|
|
|
|
|
|
die ("Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\n");
|
|
|
|
|
|
}
|
2021-03-16 01:34:17 +08:00
|
|
|
|
|
|
|
|
|
|
//定义常量
|
|
|
|
|
|
include_once "global_defines.php";
|
|
|
|
|
|
|
2021-03-23 14:49:42 +08:00
|
|
|
|
ZMAtomic::init();
|
2020-09-29 15:07:43 +08:00
|
|
|
|
try {
|
2020-12-23 11:16:24 +08:00
|
|
|
|
$sw = ZMConfig::get("global");
|
2021-01-02 13:15:50 +08:00
|
|
|
|
if (!is_dir($sw["zm_data"])) mkdir($sw["zm_data"]);
|
|
|
|
|
|
if (!is_dir($sw["config_dir"])) mkdir($sw["config_dir"]);
|
|
|
|
|
|
if (!is_dir($sw["crash_dir"])) mkdir($sw["crash_dir"]);
|
2020-09-29 15:07:43 +08:00
|
|
|
|
ManagerGM::init(ZMConfig::get("global", "swoole")["max_connection"] ?? 2048, 0.5, [
|
|
|
|
|
|
[
|
|
|
|
|
|
"key" => "connect_id",
|
|
|
|
|
|
"type" => "string",
|
|
|
|
|
|
"size" => 30
|
|
|
|
|
|
],
|
|
|
|
|
|
[
|
|
|
|
|
|
"key" => "type",
|
|
|
|
|
|
"type" => "int"
|
|
|
|
|
|
]
|
|
|
|
|
|
]);
|
|
|
|
|
|
} catch (ConnectionManager\TableException $e) {
|
|
|
|
|
|
die($e->getMessage());
|
|
|
|
|
|
}
|
2020-08-31 10:11:06 +08:00
|
|
|
|
try {
|
|
|
|
|
|
Console::init(
|
2020-12-14 01:24:34 +08:00
|
|
|
|
ZMConfig::get("global", "info_level") ?? 2,
|
2020-08-31 10:11:06 +08:00
|
|
|
|
self::$server,
|
|
|
|
|
|
$args["log-theme"] ?? "default",
|
|
|
|
|
|
($o = ZMConfig::get("console_color")) === false ? [] : $o
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai";
|
|
|
|
|
|
date_default_timezone_set($timezone);
|
|
|
|
|
|
|
2021-03-06 17:22:42 +08:00
|
|
|
|
$this->server_set = ZMConfig::get("global", "swoole");
|
2021-03-23 14:49:42 +08:00
|
|
|
|
$this->parseCliArgs(self::$argv);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
|
2021-03-02 21:24:31 +08:00
|
|
|
|
// 打印初始信息
|
|
|
|
|
|
$out["listen"] = ZMConfig::get("global", "host") . ":" . ZMConfig::get("global", "port");
|
|
|
|
|
|
if (!isset(ZMConfig::get("global", "swoole")["worker_num"])) $out["worker"] = swoole_cpu_num() . " (auto)";
|
|
|
|
|
|
else $out["worker"] = ZMConfig::get("global", "swoole")["worker_num"];
|
2021-03-06 17:22:42 +08:00
|
|
|
|
$out["environment"] = $args["env"] === null ? "default" : $args["env"];
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$out["log_level"] = Console::getLevel();
|
2021-03-13 15:16:10 +08:00
|
|
|
|
$out["version"] = ZM_VERSION . (LOAD_MODE == 0 ? (" (build " . ZM_VERSION_ID . ")") : "");
|
2021-02-09 17:09:09 +08:00
|
|
|
|
if (APP_VERSION !== "unknown") $out["app_version"] = APP_VERSION;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
if (isset(ZMConfig::get("global", "swoole")["task_worker_num"])) {
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$out["task_worker"] = ZMConfig::get("global", "swoole")["task_worker_num"];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
if (ZMConfig::get("global", "sql_config")["sql_host"] !== "") {
|
|
|
|
|
|
$conf = ZMConfig::get("global", "sql_config");
|
2021-03-02 21:31:06 +08:00
|
|
|
|
$out["mysql_pool"] = $conf["sql_database"] . "@" . $conf["sql_host"] . ":" . $conf["sql_port"];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
if (ZMConfig::get("global", "redis_config")["host"] !== "") {
|
|
|
|
|
|
$conf = ZMConfig::get("global", "redis_config");
|
|
|
|
|
|
$out["redis_pool"] = $conf["host"] . ":" . $conf["port"];
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
if (ZMConfig::get("global", "static_file_server")["status"] !== false) {
|
|
|
|
|
|
$out["static_file_server"] = "enabled";
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
2021-03-08 00:48:51 +08:00
|
|
|
|
if (self::$argv["show-php-ver"] !== false) {
|
|
|
|
|
|
$out["php_version"] = PHP_VERSION;
|
2021-03-13 15:16:10 +08:00
|
|
|
|
$out["swoole_version"] = SWOOLE_VERSION;
|
2021-03-08 00:48:51 +08:00
|
|
|
|
}
|
2021-03-02 21:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
$out["working_dir"] = DataProvider::getWorkingDir();
|
|
|
|
|
|
self::printProps($out, $tty_width, $args["log-theme"] === null);
|
|
|
|
|
|
|
2021-03-06 17:22:42 +08:00
|
|
|
|
self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port"));
|
|
|
|
|
|
|
|
|
|
|
|
self::$server->set($this->server_set);
|
2021-03-13 15:16:10 +08:00
|
|
|
|
Console::setServer(self::$server);
|
2021-03-02 21:24:31 +08:00
|
|
|
|
self::printMotd($tty_width);
|
|
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
global $asd;
|
|
|
|
|
|
$asd = get_included_files();
|
2020-09-29 15:07:43 +08:00
|
|
|
|
// 注册 Swoole Server 的事件
|
|
|
|
|
|
$this->registerServerEvents();
|
2020-11-03 21:02:24 +08:00
|
|
|
|
$r = ZMConfig::get("global", "light_cache") ?? [
|
2020-12-10 16:37:04 +08:00
|
|
|
|
"size" => 1024,
|
|
|
|
|
|
"max_strlen" => 8192,
|
|
|
|
|
|
"hash_conflict_proportion" => 0.6,
|
|
|
|
|
|
"persistence_path" => realpath(DataProvider::getDataFolder() . "_cache.json"),
|
|
|
|
|
|
"auto_save_interval" => 900
|
|
|
|
|
|
];
|
2020-11-03 21:02:24 +08:00
|
|
|
|
LightCache::init($r);
|
|
|
|
|
|
LightCacheInside::init();
|
|
|
|
|
|
SpinLock::init($r["size"]);
|
2021-01-03 18:16:35 +08:00
|
|
|
|
set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {
|
|
|
|
|
|
switch ($error_no) {
|
|
|
|
|
|
case E_WARNING:
|
|
|
|
|
|
$level_tips = 'PHP Warning: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_NOTICE:
|
|
|
|
|
|
$level_tips = 'PHP Notice: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_DEPRECATED:
|
|
|
|
|
|
$level_tips = 'PHP Deprecated: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_USER_ERROR:
|
|
|
|
|
|
$level_tips = 'User Error: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_USER_WARNING:
|
|
|
|
|
|
$level_tips = 'User Warning: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_USER_NOTICE:
|
|
|
|
|
|
$level_tips = 'User Notice: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_USER_DEPRECATED:
|
|
|
|
|
|
$level_tips = 'User Deprecated: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
case E_STRICT:
|
|
|
|
|
|
$level_tips = 'PHP Strict: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
$level_tips = 'Unkonw Type Error: ';
|
|
|
|
|
|
break;
|
|
|
|
|
|
} // do some handle
|
|
|
|
|
|
$error = $level_tips . $error_msg . ' in ' . $error_file . ' on ' . $error_line;
|
|
|
|
|
|
Console::warning($error); // 如果 return false 则错误会继续递交给 PHP 标准错误处理 /
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}, E_ALL | E_STRICT);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
} catch (Exception $e) {
|
|
|
|
|
|
Console::error("Framework初始化出现错误,请检查!");
|
|
|
|
|
|
Console::error($e->getMessage());
|
2021-03-06 17:22:42 +08:00
|
|
|
|
Console::debug($e);
|
2020-08-31 10:11:06 +08:00
|
|
|
|
die;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-02 21:24:31 +08:00
|
|
|
|
private static function printMotd($tty_width) {
|
|
|
|
|
|
if (file_exists(DataProvider::getWorkingDir() . "/config/motd.txt")) {
|
|
|
|
|
|
$motd = file_get_contents(DataProvider::getWorkingDir() . "/config/motd.txt");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$motd = file_get_contents(__DIR__ . "/../../config/motd.txt");
|
|
|
|
|
|
}
|
|
|
|
|
|
$motd = explode("\n", $motd);
|
|
|
|
|
|
foreach ($motd as $k => $v) {
|
|
|
|
|
|
$motd[$k] = substr($v, 0, $tty_width);
|
|
|
|
|
|
}
|
|
|
|
|
|
$motd = implode("\n", $motd);
|
|
|
|
|
|
echo $motd;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-10 16:37:04 +08:00
|
|
|
|
public function start() {
|
|
|
|
|
|
self::$server->start();
|
2021-03-15 02:54:16 +08:00
|
|
|
|
zm_atomic("server_is_stopped")->set(1);
|
2021-03-23 14:49:42 +08:00
|
|
|
|
Console::setLevel(0);
|
2020-12-10 16:37:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-31 10:11:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 从全局配置文件里读取注入系统事件的类
|
|
|
|
|
|
* @throws ReflectionException
|
|
|
|
|
|
* @throws ReflectionException
|
|
|
|
|
|
*/
|
|
|
|
|
|
private function registerServerEvents() {
|
|
|
|
|
|
$all_event_class = ZMConfig::get("global", "server_event_handler_class") ?? [];
|
|
|
|
|
|
if (!in_array(ServerEventHandler::class, $all_event_class)) {
|
|
|
|
|
|
$all_event_class[] = ServerEventHandler::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];
|
2020-12-14 01:24:34 +08:00
|
|
|
|
if ($annotation instanceof SwooleHandler) {
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$annotation->class = $v;
|
|
|
|
|
|
$annotation->method = $vs->getName();
|
|
|
|
|
|
$event_list[strtolower($annotation->event)] = $annotation;
|
2020-12-14 01:24:34 +08:00
|
|
|
|
} elseif ($annotation instanceof OnSetup) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$annotation->class = $v;
|
|
|
|
|
|
$annotation->method = $vs->getName();
|
|
|
|
|
|
$c = new $v();
|
|
|
|
|
|
$m = $annotation->method;
|
|
|
|
|
|
$c->$m();
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach ($event_list as $k => $v) {
|
2021-01-02 13:15:50 +08:00
|
|
|
|
$c = ZMUtil::getModInstance($v->class);
|
|
|
|
|
|
$m = $v->method;
|
|
|
|
|
|
self::$server->on($k, function (...$param) use ($c, $m) { $c->$m(...$param); });
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 解析命令行的 $argv 参数们
|
|
|
|
|
|
* @param $args
|
2021-03-23 14:49:42 +08:00
|
|
|
|
* @throws Exception
|
2020-08-31 10:11:06 +08:00
|
|
|
|
*/
|
2021-03-23 14:49:42 +08:00
|
|
|
|
private function parseCliArgs($args) {
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$coroutine_mode = true;
|
|
|
|
|
|
global $terminal_id;
|
2021-02-21 22:17:34 +08:00
|
|
|
|
$terminal_id = uuidgen();
|
2020-08-31 10:11:06 +08:00
|
|
|
|
foreach ($args as $x => $y) {
|
|
|
|
|
|
switch ($x) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
case 'disable-coroutine':
|
2020-11-03 21:02:24 +08:00
|
|
|
|
if ($y) {
|
2020-09-29 15:07:43 +08:00
|
|
|
|
$coroutine_mode = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
case 'debug-mode':
|
2020-11-03 21:02:24 +08:00
|
|
|
|
if ($y || ZMConfig::get("global", "debug_mode")) {
|
2020-08-31 10:11:06 +08:00
|
|
|
|
$coroutine_mode = false;
|
|
|
|
|
|
$terminal_id = null;
|
|
|
|
|
|
Console::warning("You are in debug mode, do not use in production!");
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'daemon':
|
|
|
|
|
|
if ($y) {
|
|
|
|
|
|
$this->server_set["daemonize"] = 1;
|
2021-01-29 20:47:00 +08:00
|
|
|
|
Console::$theme = "no-color";
|
2020-08-31 10:11:06 +08:00
|
|
|
|
Console::log("已启用守护进程,输出重定向到 " . $this->server_set["log_file"]);
|
|
|
|
|
|
$terminal_id = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'disable-console-input':
|
2021-01-07 16:01:01 +08:00
|
|
|
|
case 'no-interaction':
|
2020-08-31 10:11:06 +08:00
|
|
|
|
if ($y) $terminal_id = null;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-error':
|
|
|
|
|
|
if ($y) Console::setLevel(0);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-warning':
|
|
|
|
|
|
if ($y) Console::setLevel(1);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-info':
|
|
|
|
|
|
if ($y) Console::setLevel(2);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-verbose':
|
2021-01-07 16:01:01 +08:00
|
|
|
|
case 'verbose':
|
2020-08-31 10:11:06 +08:00
|
|
|
|
if ($y) Console::setLevel(3);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-debug':
|
|
|
|
|
|
if ($y) Console::setLevel(4);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'log-theme':
|
2020-09-29 15:07:43 +08:00
|
|
|
|
if ($y !== null) {
|
2020-08-31 10:11:06 +08:00
|
|
|
|
Console::$theme = $y;
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2021-03-08 00:48:51 +08:00
|
|
|
|
case 'show-php-ver':
|
2021-01-07 16:01:01 +08:00
|
|
|
|
default:
|
2021-01-13 15:40:27 +08:00
|
|
|
|
//Console::info("Calculating ".$x);
|
|
|
|
|
|
//dump($y);
|
2021-01-07 16:01:01 +08:00
|
|
|
|
break;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($coroutine_mode) Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-02 21:24:31 +08:00
|
|
|
|
private static function writeNoDouble($k, $v, &$line_data, &$line_width, &$current_line, $colorful, $max_border) {
|
|
|
|
|
|
$tmp_line = $k . ": " . $v;
|
|
|
|
|
|
//Console::info("写入[".$tmp_line."]");
|
|
|
|
|
|
if (strlen($tmp_line) >= $line_width[$current_line]) { //输出的内容太多了,以至于一行都放不下一个,要折行
|
|
|
|
|
|
$title_strlen = strlen($k . ": ");
|
|
|
|
|
|
$content_len = $line_width[$current_line] - $title_strlen;
|
|
|
|
|
|
|
|
|
|
|
|
$line_data[$current_line] = " " . $k . ": ";
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::color8(32);
|
|
|
|
|
|
$line_data[$current_line] .= substr($v, 0, $content_len);
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
$rest = substr($v, $content_len);
|
|
|
|
|
|
++$current_line; // 带标题的第一行满了,折到第二行
|
|
|
|
|
|
do {
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] = TermColor::color8(32);
|
|
|
|
|
|
$line_data[$current_line] .= " " . substr($rest, 0, $max_border - 2);
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
$rest = substr($rest, $max_border - 2);
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
} while ($rest > $max_border - 2); // 循环,直到放完
|
|
|
|
|
|
} else { // 不需要折行
|
|
|
|
|
|
//Console::info("不需要折行");
|
|
|
|
|
|
$line_data[$current_line] = " " . $k . ": ";
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::color8(32);
|
|
|
|
|
|
$line_data[$current_line] .= $v;
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
|
|
|
|
|
|
if ($max_border >= 57) {
|
|
|
|
|
|
if (strlen($tmp_line) >= intval(($max_border - 2) / 2)) { // 不需要折行,直接输出一个转下一行
|
|
|
|
|
|
//Console::info("不需要折行,直接输出一个转下一行");
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
} else { // 输出很小,写到前面并分片
|
|
|
|
|
|
//Console::info("输出很小,写到前面并分片");
|
|
|
|
|
|
$space = intval($max_border / 2) - 2 - strlen($tmp_line);
|
2021-03-18 14:56:35 +08:00
|
|
|
|
$line_data[$current_line] .= str_pad("", $space);
|
2021-03-02 21:24:31 +08:00
|
|
|
|
$line_data[$current_line] .= "| "; // 添加分片
|
|
|
|
|
|
$line_width[$current_line] -= (strlen($tmp_line) + 3 + $space);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static function printProps($out, $tty_width, $colorful = true) {
|
|
|
|
|
|
$max_border = $tty_width < 65 ? $tty_width : 65;
|
|
|
|
|
|
if (LOAD_MODE == 0) echo Console::setColor("* Framework started with source mode.\n", $colorful ? "yellow" : "");
|
|
|
|
|
|
echo str_pad("", $max_border, "=") . PHP_EOL;
|
|
|
|
|
|
|
|
|
|
|
|
$current_line = 0;
|
|
|
|
|
|
$line_width = [];
|
|
|
|
|
|
$line_data = [];
|
|
|
|
|
|
foreach ($out as $k => $v) {
|
2021-03-06 17:22:42 +08:00
|
|
|
|
start:
|
2021-03-02 21:24:31 +08:00
|
|
|
|
if (!isset($line_width[$current_line])) {
|
|
|
|
|
|
$line_width[$current_line] = $max_border - 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
//Console::info("行宽[$current_line]:".$line_width[$current_line]);
|
|
|
|
|
|
if ($max_border >= 57) { // 很宽的时候,一行能放两个短行
|
|
|
|
|
|
if ($line_width[$current_line] == ($max_border - 2)) { //空行
|
|
|
|
|
|
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
|
|
|
|
|
} else { // 不是空行,已经有东西了
|
|
|
|
|
|
$tmp_line = $k . ": " . $v;
|
|
|
|
|
|
//Console::info("[$current_line]即将插入后面的东西[".$tmp_line."]");
|
|
|
|
|
|
if (strlen($tmp_line) > $line_width[$current_line]) { // 地方不够,另起一行
|
|
|
|
|
|
$line_data[$current_line] = str_replace("| ", "", $line_data[$current_line]);
|
|
|
|
|
|
++$current_line;
|
2021-03-06 17:22:42 +08:00
|
|
|
|
goto start;
|
2021-03-02 21:24:31 +08:00
|
|
|
|
} else { // 地方够,直接写到后面并另起一行
|
|
|
|
|
|
$line_data[$current_line] .= $k . ": ";
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::color8(32);
|
|
|
|
|
|
$line_data[$current_line] .= $v;
|
|
|
|
|
|
if ($colorful) $line_data[$current_line] .= TermColor::RESET;
|
|
|
|
|
|
++$current_line;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else { // 不够宽,直接写单行
|
|
|
|
|
|
self::writeNoDouble($k, $v, $line_data, $line_width, $current_line, $colorful, $max_border);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
foreach ($line_data as $v) {
|
|
|
|
|
|
echo $v . PHP_EOL;
|
|
|
|
|
|
}
|
|
|
|
|
|
echo str_pad("", $max_border, "=") . PHP_EOL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-18 14:56:35 +08:00
|
|
|
|
public static function getTtyWidth(): string {
|
2020-08-31 10:11:06 +08:00
|
|
|
|
return explode(" ", trim(exec("stty size")))[1];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|