add cs fixer and PHPStan and activate it (build 436)

This commit is contained in:
crazywhalecc
2022-03-15 18:05:33 +08:00
parent d01bd69aa5
commit 1706afbcd0
163 changed files with 4572 additions and 3588 deletions

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command;
@@ -16,44 +17,52 @@ class BuildCommand extends Command
{
// the name of the command (the part after "bin/console")
protected static $defaultName = 'build';
/**
* @var OutputInterface
*/
private $output = null;
private $output;
protected function configure() {
$this->setDescription("Build an \".phar\" file | 将项目构建一个phar包");
$this->setHelp("此功能将会把整个项目打包为phar");
$this->addOption("target", "D", InputOption::VALUE_REQUIRED, "Output Directory | 指定输出目录");
protected function configure()
{
$this->setDescription('Build an ".phar" file | 将项目构建一个phar包');
$this->setHelp('此功能将会把整个项目打包为phar');
$this->addOption('target', 'D', InputOption::VALUE_REQUIRED, 'Output Directory | 指定输出目录');
// ...
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->output = $output;
$target_dir = $input->getOption("target") ?? (WORKING_DIR);
if (mb_strpos($target_dir, "../")) $target_dir = realpath($target_dir);
$target_dir = $input->getOption('target') ?? (WORKING_DIR);
if (mb_strpos($target_dir, '../')) {
$target_dir = realpath($target_dir);
}
if ($target_dir === false) {
$output->writeln(TermColor::color8(31) . zm_internal_errcode("E00039") . "Error: No such file or directory (" . $target_dir . ")" . TermColor::RESET);
$output->writeln(TermColor::color8(31) . zm_internal_errcode('E00039') . 'Error: No such file or directory (' . $target_dir . ')' . TermColor::RESET);
return 1;
}
$output->writeln("Target: " . $target_dir);
if (mb_substr($target_dir, -1, 1) !== '/') $target_dir .= "/";
$output->writeln('Target: ' . $target_dir);
if (mb_substr($target_dir, -1, 1) !== '/') {
$target_dir .= '/';
}
if (ini_get('phar.readonly') == 1) {
$output->writeln(TermColor::color8(31) . zm_internal_errcode("E00040") . "You need to set \"phar.readonly\" to \"Off\"!");
$output->writeln(TermColor::color8(31) . "See: https://stackoverflow.com/questions/34667606/cant-enable-phar-writing");
$output->writeln(TermColor::color8(31) . zm_internal_errcode('E00040') . 'You need to set "phar.readonly" to "Off"!');
$output->writeln(TermColor::color8(31) . 'See: https://stackoverflow.com/questions/34667606/cant-enable-phar-writing');
return 1;
}
if (!is_dir($target_dir)) {
$output->writeln(TermColor::color8(31) . zm_internal_errcode("E00039") . "Error: No such file or directory ($target_dir)" . TermColor::RESET);
$output->writeln(TermColor::color8(31) . zm_internal_errcode('E00039') . "Error: No such file or directory ({$target_dir})" . TermColor::RESET);
return 1;
}
$filename = "server.phar";
$filename = 'server.phar';
$this->build($target_dir, $filename);
return 0;
}
private function build($target_dir, $filename) {
private function build($target_dir, $filename)
{
@unlink($target_dir . $filename);
$phar = new Phar($target_dir . $filename);
$phar->startBuffering();
@@ -62,7 +71,7 @@ class BuildCommand extends Command
$all = DataProvider::scanDirFiles(DataProvider::getSourceRootDir(), true, true);
$all = array_filter($all, function ($x) {
$dirs = preg_match("/(^(bin|config|resources|src|vendor)\/|^(composer\.json|README\.md)$)/", $x);
$dirs = preg_match('/(^(bin|config|resources|src|vendor)\\/|^(composer\\.json|README\\.md)$)/', $x);
return !($dirs !== 1);
});
@@ -71,15 +80,15 @@ class BuildCommand extends Command
$archive_dir = DataProvider::getSourceRootDir();
foreach ($all as $k => $v) {
$phar->addFile($archive_dir . "/" . $v, $v);
$progress->current($k + 1, "Adding " . $v);
$phar->addFile($archive_dir . '/' . $v, $v);
$progress->current($k + 1, 'Adding ' . $v);
}
$phar->setStub(
"#!/usr/bin/env php\n" .
$phar->createDefaultStub(LOAD_MODE == 0 ? "src/entry.php" : "vendor/zhamao/framework/src/entry.php")
$phar->createDefaultStub(LOAD_MODE == 0 ? 'src/entry.php' : 'vendor/zhamao/framework/src/entry.php')
);
$phar->stopBuffering();
$this->output->writeln("Successfully built. Location: " . $target_dir . "$filename");
$this->output->writeln('Successfully built. Location: ' . $target_dir . "{$filename}");
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command;
@@ -14,49 +15,53 @@ class CheckConfigCommand extends Command
private $need_update = false;
protected function configure() {
$this->setDescription("检查配置文件是否和框架当前版本有更新");
protected function configure()
{
$this->setDescription('检查配置文件是否和框架当前版本有更新');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (LOAD_MODE !== 1) {
$output->writeln("<error>仅限在Composer依赖模式中使用此命令</error>");
$output->writeln('<error>仅限在Composer依赖模式中使用此命令</error>');
return 1;
}
$current_cfg = getcwd() . "/config/";
$remote_cfg = include_once FRAMEWORK_ROOT_DIR . "/config/global.php";
if (file_exists($current_cfg . "global.php")) {
$this->check($remote_cfg, "global.php", $output);
$current_cfg = getcwd() . '/config/';
$remote_cfg = include_once FRAMEWORK_ROOT_DIR . '/config/global.php';
if (file_exists($current_cfg . 'global.php')) {
$this->check($remote_cfg, 'global.php', $output);
}
if (file_exists($current_cfg . "global.development.php")) {
$this->check($remote_cfg, "global.development.php", $output);
if (file_exists($current_cfg . 'global.development.php')) {
$this->check($remote_cfg, 'global.development.php', $output);
}
if (file_exists($current_cfg . "global.staging.php")) {
$this->check($remote_cfg, "global.staging.php", $output);
if (file_exists($current_cfg . 'global.staging.php')) {
$this->check($remote_cfg, 'global.staging.php', $output);
}
if (file_exists($current_cfg . "global.production.php")) {
$this->check($remote_cfg, "global.production.php", $output);
if (file_exists($current_cfg . 'global.production.php')) {
$this->check($remote_cfg, 'global.production.php', $output);
}
if ($this->need_update === true) {
$output->writeln("<comment>有配置文件需要更新,详情见文档 `https://framework.zhamao.xin/update/config`</comment>");
$output->writeln('<comment>有配置文件需要更新,详情见文档 `https://framework.zhamao.xin/update/config`</comment>');
} else {
$output->writeln("<info>配置文件暂无更新!</info>");
$output->writeln('<info>配置文件暂无更新!</info>');
}
return 0;
}
/**
* @noinspection PhpIncludeInspection
* @param mixed $remote
* @param mixed $local
*/
private function check($remote, $local, OutputInterface $out) {
$local_file = include_once WORKING_DIR . "/config/".$local;
private function check($remote, $local, OutputInterface $out)
{
$local_file = include_once WORKING_DIR . '/config/' . $local;
if ($local_file === true) {
$local_file = ZMConfig::get("global");
$local_file = ZMConfig::get('global');
}
foreach($remote as $k => $v) {
foreach ($remote as $k => $v) {
if (!isset($local_file[$k])) {
$out->writeln("<comment>配置文件 ".$local . " 需要更新!(当前配置文件缺少 `$k` 字段配置)</comment>");
$out->writeln('<comment>配置文件 ' . $local . " 需要更新!(当前配置文件缺少 `{$k}` 字段配置)</comment>");
$this->need_update = true;
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Daemon;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -11,16 +11,17 @@ use ZM\Framework;
abstract class DaemonCommand extends Command
{
protected $daemon_file = null;
protected $daemon_file;
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
$file = Framework::getProcessState(ZM_PROCESS_MASTER);
if ($file === false || posix_getsid(intval($file["pid"])) === false) {
$output->writeln("<comment>未检测到正在运行的守护进程或框架进程!</comment>");
if ($file === false || posix_getsid(intval($file['pid'])) === false) {
$output->writeln('<comment>未检测到正在运行的守护进程或框架进程!</comment>');
Framework::removeProcessState(ZM_PROCESS_MASTER);
die();
exit(1);
}
$this->daemon_file = $file;
return 0;
}
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Daemon;
@@ -11,14 +12,16 @@ class DaemonReloadCommand extends DaemonCommand
{
protected static $defaultName = 'daemon:reload';
protected function configure() {
$this->setDescription("重载框架");
protected function configure()
{
$this->setDescription('重载框架');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);
Process::kill(intval($this->daemon_file["pid"]), SIGUSR1);
$output->writeln("<info>成功重载!</info>");
Process::kill(intval($this->daemon_file['pid']), SIGUSR1);
$output->writeln('<info>成功重载!</info>');
return 0;
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Daemon;
@@ -10,20 +11,23 @@ class DaemonStatusCommand extends DaemonCommand
{
protected static $defaultName = 'daemon:status';
protected function configure() {
$this->setDescription("查看框架的运行状态");
protected function configure()
{
$this->setDescription('查看框架的运行状态');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);
$output->writeln("<info>框架" . ($this->daemon_file["daemon"] ? "以守护进程模式" : "") . "运行中pid" . $this->daemon_file["pid"] . "</info>");
if ($this->daemon_file["daemon"]) {
$output->writeln("<comment>----- 以下是stdout内容 -----</comment>");
$stdout = file_get_contents($this->daemon_file["stdout"]);
$output->writeln('<info>框架' . ($this->daemon_file['daemon'] ? '以守护进程模式' : '') . '运行中pid' . $this->daemon_file['pid'] . '</info>');
if ($this->daemon_file['daemon']) {
$output->writeln('<comment>----- 以下是stdout内容 -----</comment>');
$stdout = file_get_contents($this->daemon_file['stdout']);
$stdout = explode("\n", $stdout);
for ($i = 15; $i > 0; --$i) {
if (isset($stdout[count($stdout) - $i]))
if (isset($stdout[count($stdout) - $i])) {
echo $stdout[count($stdout) - $i] . PHP_EOL;
}
}
}
return 0;

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Daemon;
@@ -12,22 +13,24 @@ class DaemonStopCommand extends DaemonCommand
{
protected static $defaultName = 'daemon:stop';
protected function configure() {
$this->setDescription("停止运行的框架");
protected function configure()
{
$this->setDescription('停止运行的框架');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);
Process::kill(intval($this->daemon_file["pid"]), SIGTERM);
Process::kill(intval($this->daemon_file['pid']), SIGTERM);
$i = 10;
while (Framework::getProcessState(ZM_PROCESS_MASTER) !== false && $i > 0) {
sleep(1);
--$i;
}
if ($i === 0) {
$output->writeln("<error>停止失败请检查进程pid #" . $this->daemon_file["pid"] . " 是否响应!</error>");
$output->writeln('<error>停止失败请检查进程pid #' . $this->daemon_file['pid'] . ' 是否响应!</error>');
} else {
$output->writeln("<info>成功停止!</info>");
$output->writeln('<info>成功停止!</info>');
}
return 0;
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Generate;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -15,28 +15,31 @@ class SystemdGenerateCommand extends Command
// the name of the command (the part after "bin/console")
protected static $defaultName = 'generate:systemd';
protected function configure() {
$this->setDescription("生成框架的 systemd 配置文件");
protected function configure()
{
$this->setDescription('生成框架的 systemd 配置文件');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
$path = $this->generate();
$output->writeln("<info>成功生成 systemd 文件,位置:" . $path . "</info>");
$output->writeln("<info>有关如何使用 systemd 配置文件,请访问 `https://github.com/zhamao-robot/zhamao-framework/issues/36`</info>");
$output->writeln('<info>成功生成 systemd 文件,位置:' . $path . '</info>');
$output->writeln('<info>有关如何使用 systemd 配置文件,请访问 `https://github.com/zhamao-robot/zhamao-framework/issues/36`</info>');
return 0;
}
private function generate() {
private function generate()
{
$s = "[Unit]\nDescription=zhamao-framework Daemon\nAfter=rc-local.service\n\n[Service]\nType=simple";
$s .= "\nUser=" . exec("whoami");
$s .= "\nUser=" . exec('whoami');
$s .= "\nGroup=" . exec("groups | awk '{print $1}'");
$s .= "\nWorkingDirectory=" . getcwd();
global $argv;
$s .= "\nExecStart=" . PHP_BINARY . " {$argv[0]} server";
$s .= "\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n";
@mkdir(getcwd() . "/resources/");
file_put_contents(ZMConfig::get("global", "zm_data") . "zhamao.service", $s);
return ZMConfig::get("global", "zm_data") . "zhamao.service";
@mkdir(getcwd() . '/resources/');
file_put_contents(ZMConfig::get('global', 'zm_data') . 'zhamao.service', $s);
return ZMConfig::get('global', 'zm_data') . 'zhamao.service';
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command;
@@ -11,99 +12,107 @@ use Symfony\Component\Console\Output\OutputInterface;
class InitCommand extends Command
{
private $extract_files = [
"/zhamao",
"/config/global.php",
"/.gitignore",
"/config/file_header.json",
"/config/console_color.json",
"/config/motd.txt",
"/src/Module/Example/Hello.php",
"/src/Module/Middleware/TimerMiddleware.php",
"/src/Custom/global_function.php"
];
// the name of the command (the part after "bin/console")
protected static $defaultName = 'init';
protected function configure() {
$this->setDescription("Initialize framework starter | 初始化框架运行的基础文件");
private $extract_files = [
'/zhamao',
'/config/global.php',
'/.gitignore',
'/config/file_header.json',
'/config/console_color.json',
'/config/motd.txt',
'/src/Module/Example/Hello.php',
'/src/Module/Middleware/TimerMiddleware.php',
'/src/Custom/global_function.php',
];
protected function configure()
{
$this->setDescription('Initialize framework starter | 初始化框架运行的基础文件');
$this->setDefinition([
new InputOption("force", "F", null, "强制重制,覆盖现有文件")
new InputOption('force', 'F', null, '强制重制,覆盖现有文件'),
]);
$this->setHelp("此命令将会解压以下文件到项目的根目录:\n" . implode("\n", $this->getExtractFiles()));
// ...
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (LOAD_MODE === 1) { // 从composer依赖而来的项目模式最基本的需要初始化的模式
$output->writeln("<comment>Initializing files</comment>");
$output->writeln('<comment>Initializing files</comment>');
$base_path = WORKING_DIR;
$args = $input->getOption("force");
$args = $input->getOption('force');
foreach ($this->extract_files as $file) {
if (!file_exists($base_path . $file) || $args) {
$info = pathinfo($file);
@mkdir($base_path . $info["dirname"], 0777, true);
echo "Copying " . $file . PHP_EOL;
$package_name = (json_decode(file_get_contents(__DIR__ . "/../../../composer.json"), true)["name"]);
copy($base_path . "/vendor/" . $package_name . $file, $base_path . $file);
@mkdir($base_path . $info['dirname'], 0777, true);
echo 'Copying ' . $file . PHP_EOL;
$package_name = (json_decode(file_get_contents(__DIR__ . '/../../../composer.json'), true)['name']);
copy($base_path . '/vendor/' . $package_name . $file, $base_path . $file);
} else {
echo "Skipping " . $file . " , file exists." . PHP_EOL;
echo 'Skipping ' . $file . ' , file exists.' . PHP_EOL;
}
}
chmod($base_path . "/zhamao", 0755);
chmod($base_path . '/zhamao', 0755);
$autoload = [
"psr-4" => [
"Module\\" => "src/Module",
"Custom\\" => "src/Custom"
'psr-4' => [
'Module\\' => 'src/Module',
'Custom\\' => 'src/Custom',
],
'files' => [
'src/Custom/global_function.php',
],
"files" => [
"src/Custom/global_function.php"
]
];
if (file_exists($base_path . "/composer.json")) {
$composer = json_decode(file_get_contents($base_path . "/composer.json"), true);
if (!isset($composer["autoload"])) {
$composer["autoload"] = $autoload;
if (file_exists($base_path . '/composer.json')) {
$composer = json_decode(file_get_contents($base_path . '/composer.json'), true);
if (!isset($composer['autoload'])) {
$composer['autoload'] = $autoload;
} else {
foreach ($autoload["psr-4"] as $k => $v) {
if (!isset($composer["autoload"]["psr-4"][$k])) $composer["autoload"]["psr-4"][$k] = $v;
foreach ($autoload['psr-4'] as $k => $v) {
if (!isset($composer['autoload']['psr-4'][$k])) {
$composer['autoload']['psr-4'][$k] = $v;
}
}
foreach ($autoload["files"] as $v) {
if (!in_array($v, $composer["autoload"]["files"])) $composer["autoload"]["files"][] = $v;
foreach ($autoload['files'] as $v) {
if (!in_array($v, $composer['autoload']['files'])) {
$composer['autoload']['files'][] = $v;
}
}
}
file_put_contents($base_path . "/composer.json", json_encode($composer, 64 | 128 | 256));
$output->writeln("<info>Executing composer command: `composer dump-autoload`</info>");
exec("composer dump-autoload");
file_put_contents($base_path . '/composer.json', json_encode($composer, 64 | 128 | 256));
$output->writeln('<info>Executing composer command: `composer dump-autoload`</info>');
exec('composer dump-autoload');
echo PHP_EOL;
} else {
echo(zm_internal_errcode("E00041") . "Error occurred. Please check your updates.\n");
echo zm_internal_errcode('E00041') . "Error occurred. Please check your updates.\n";
return 1;
}
$output->writeln("<info>Done!</info>");
$output->writeln('<info>Done!</info>');
return 0;
} elseif (LOAD_MODE === 2) { //从phar启动的框架包初始化的模式
}
if (LOAD_MODE === 2) { //从phar启动的框架包初始化的模式
$phar_link = new Phar(__DIR__);
$current_dir = pathinfo($phar_link->getPath())["dirname"];
$current_dir = pathinfo($phar_link->getPath())['dirname'];
chdir($current_dir);
$phar_link = "phar://" . $phar_link->getPath();
$phar_link = 'phar://' . $phar_link->getPath();
foreach ($this->extract_files as $file) {
if (!file_exists($current_dir . $file)) {
$info = pathinfo($file);
@mkdir($current_dir . $info["dirname"], 0777, true);
echo "Copying " . $file . PHP_EOL;
@mkdir($current_dir . $info['dirname'], 0777, true);
echo 'Copying ' . $file . PHP_EOL;
file_put_contents($current_dir . $file, file_get_contents($phar_link . $file));
} else {
echo "Skipping " . $file . " , file exists." . PHP_EOL;
echo 'Skipping ' . $file . ' , file exists.' . PHP_EOL;
}
}
}
$output->writeln(zm_internal_errcode("E00042") . "initialization must be started with composer-project mode!");
$output->writeln(zm_internal_errcode('E00042') . 'initialization must be started with composer-project mode!');
return 1;
}
private function getExtractFiles(): array {
private function getExtractFiles(): array
{
return $this->extract_files;
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Module;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -14,67 +14,78 @@ use ZM\Utils\Manager\ModuleManager;
class ModuleListCommand extends Command
{
// the name of the command (the part after "bin/console")
// the name of the command (the part after "bin/console")
protected static $defaultName = 'module:list';
protected function configure() {
$this->setDescription("查看所有模块信息");
$this->setHelp("此功能将会把炸毛框架的模块列举出来。");
protected function configure()
{
$this->setDescription('查看所有模块信息');
$this->setHelp('此功能将会把炸毛框架的模块列举出来。');
// ...
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
ZMConfig::setEnv($args["env"] ?? "");
if (ZMConfig::get("global") === false) {
die (zm_internal_errcode("E00007") . "Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
ZMConfig::setEnv($args['env'] ?? '');
if (ZMConfig::get('global') === false) {
exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
}
//定义常量
/** @noinspection PhpIncludeInspection */
include_once DataProvider::getFrameworkRootDir() . "/src/ZM/global_defines.php";
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
Console::init(
ZMConfig::get("global", "info_level") ?? 2,
ZMConfig::get('global', 'info_level') ?? 2,
null,
$args["log-theme"] ?? "default",
($o = ZMConfig::get("console_color")) === false ? [] : $o
$args['log-theme'] ?? 'default',
($o = ZMConfig::get('console_color')) === false ? [] : $o
);
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai";
$timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
date_default_timezone_set($timezone);
$list = ModuleManager::getConfiguredModules();
foreach ($list as $v) {
echo "[" . Console::setColor($v["name"], "green") . "]" . PHP_EOL;
$out_list = ["类型" => "源码(source)"];
if (isset($v["version"])) $out_list["版本"] = $v["version"];
if (isset($v["description"])) $out_list["描述"] = $v["description"];
$out_list["目录"] = str_replace(DataProvider::getSourceRootDir() . "/", "", $v["module-path"]);
echo '[' . Console::setColor($v['name'], 'green') . ']' . PHP_EOL;
$out_list = ['类型' => '源码(source)'];
if (isset($v['version'])) {
$out_list['版本'] = $v['version'];
}
if (isset($v['description'])) {
$out_list['描述'] = $v['description'];
}
$out_list['目录'] = str_replace(DataProvider::getSourceRootDir() . '/', '', $v['module-path']);
$this->printList($out_list);
}
if ($list === []) {
echo Console::setColor("没有发现已编写打包配置文件zm.json的模块", "yellow") . PHP_EOL;
echo Console::setColor('没有发现已编写打包配置文件zm.json的模块', 'yellow') . PHP_EOL;
}
$list = ModuleManager::getPackedModules();
foreach ($list as $v) {
echo "[" . Console::setColor($v["name"], "gold") . "]" . PHP_EOL;
$out_list = ["类型" => "模块包(phar)"];
if (isset($v["module-config"]["version"])) $out_list["版本"] = $v["module-config"]["version"];
if (isset($v["module-config"]["description"])) $out_list["描述"] = $v["module-config"]["description"];
$out_list["位置"] = str_replace(DataProvider::getSourceRootDir() . "/", "", $v["phar-path"]);
echo '[' . Console::setColor($v['name'], 'gold') . ']' . PHP_EOL;
$out_list = ['类型' => '模块包(phar)'];
if (isset($v['module-config']['version'])) {
$out_list['版本'] = $v['module-config']['version'];
}
if (isset($v['module-config']['description'])) {
$out_list['描述'] = $v['module-config']['description'];
}
$out_list['位置'] = str_replace(DataProvider::getSourceRootDir() . '/', '', $v['phar-path']);
$this->printList($out_list);
}
if ($list === []) {
echo Console::setColor("没有发现已打包且装载的模块!", "yellow") . PHP_EOL;
echo Console::setColor('没有发现已打包且装载的模块!', 'yellow') . PHP_EOL;
}
return 0;
}
private function printList($list) {
private function printList($list)
{
foreach ($list as $k => $v) {
echo "\t" . $k . ": " . Console::setColor($v, "yellow") . PHP_EOL;
echo "\t" . $k . ': ' . Console::setColor($v, 'yellow') . PHP_EOL;
}
}
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Module;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -19,42 +19,47 @@ class ModulePackCommand extends Command
// the name of the command (the part after "bin/console")
protected static $defaultName = 'module:pack';
protected function configure() {
$this->addArgument("module-name", InputArgument::REQUIRED);
$this->setDescription("将配置好的模块构建一个phar包");
$this->setHelp("此功能将会把炸毛框架的模块打包为\".phar\",供发布和执行。");
$this->addOption("target", "D", InputOption::VALUE_REQUIRED, "Output Directory | 指定输出目录");
protected function configure()
{
$this->addArgument('module-name', InputArgument::REQUIRED);
$this->setDescription('将配置好的模块构建一个phar包');
$this->setHelp('此功能将会把炸毛框架的模块打包为".phar",供发布和执行。');
$this->addOption('target', 'D', InputOption::VALUE_REQUIRED, 'Output Directory | 指定输出目录');
// ...
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
ZMConfig::setEnv($args["env"] ?? "");
if (ZMConfig::get("global") === false) {
die (zm_internal_errcode("E00007") . "Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
ZMConfig::setEnv($args['env'] ?? '');
if (ZMConfig::get('global') === false) {
exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
}
//定义常量
include_once DataProvider::getFrameworkRootDir()."/src/ZM/global_defines.php";
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
Console::init(
ZMConfig::get("global", "info_level") ?? 2,
ZMConfig::get('global', 'info_level') ?? 2,
null,
$args["log-theme"] ?? "default",
($o = ZMConfig::get("console_color")) === false ? [] : $o
$args['log-theme'] ?? 'default',
($o = ZMConfig::get('console_color')) === false ? [] : $o
);
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai";
$timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
date_default_timezone_set($timezone);
$list = ModuleManager::getConfiguredModules();
if (!isset($list[$input->getArgument("module-name")])) {
$output->writeln("<error>不存在模块 ".$input->getArgument("module-name")." !</error>");
if (!isset($list[$input->getArgument('module-name')])) {
$output->writeln('<error>不存在模块 ' . $input->getArgument('module-name') . ' !</error>');
return 1;
}
$result = ModuleManager::packModule($list[$input->getArgument("module-name")], $input->getOption("target"));
if ($result) Console::success("打包完成!");
else Console::error("打包失败!");
$result = ModuleManager::packModule($list[$input->getArgument('module-name')], $input->getOption('target'));
if ($result) {
Console::success('打包完成!');
} else {
Console::error('打包失败!');
}
return 0;
}
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Module;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@@ -16,51 +16,56 @@ use ZM\Utils\Manager\ModuleManager;
class ModuleUnpackCommand extends Command
{
// the name of the command (the part after "bin/console")
// the name of the command (the part after "bin/console")
protected static $defaultName = 'module:unpack';
protected function configure() {
protected function configure()
{
$this->setDefinition([
new InputArgument("module-name", InputArgument::REQUIRED),
new InputOption("overwrite-light-cache", null, null, "覆盖现有的LightCache项目"),
new InputOption("overwrite-zm-data", null, null, "覆盖现有的zm_data文件"),
new InputOption("overwrite-source", null, null, "覆盖现有的源码文件"),
new InputOption("ignore-depends", null, null, "解包时忽略检查依赖")
new InputArgument('module-name', InputArgument::REQUIRED),
new InputOption('overwrite-light-cache', null, null, '覆盖现有的LightCache项目'),
new InputOption('overwrite-zm-data', null, null, '覆盖现有的zm_data文件'),
new InputOption('overwrite-source', null, null, '覆盖现有的源码文件'),
new InputOption('ignore-depends', null, null, '解包时忽略检查依赖'),
]);
$this->setDescription("解包一个phar模块到src目录");
$this->setHelp("此功能将phar格式的模块包解包到src目录下。");
$this->setDescription('解包一个phar模块到src目录');
$this->setHelp('此功能将phar格式的模块包解包到src目录下。');
// ...
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
ZMConfig::setEnv($args["env"] ?? "");
if (ZMConfig::get("global") === false) {
die (zm_internal_errcode("E00007") . "Global config load failed: " . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
ZMConfig::setEnv($args['env'] ?? '');
if (ZMConfig::get('global') === false) {
exit(zm_internal_errcode('E00007') . 'Global config load failed: ' . ZMConfig::$last_error . "\nPlease init first!\nSee: https://github.com/zhamao-robot/zhamao-framework/issues/37\n");
}
//定义常量
/** @noinspection PhpIncludeInspection */
include_once DataProvider::getFrameworkRootDir()."/src/ZM/global_defines.php";
include_once DataProvider::getFrameworkRootDir() . '/src/ZM/global_defines.php';
Console::init(
ZMConfig::get("global", "info_level") ?? 4,
ZMConfig::get('global', 'info_level') ?? 4,
null,
$args["log-theme"] ?? "default",
($o = ZMConfig::get("console_color")) === false ? [] : $o
$args['log-theme'] ?? 'default',
($o = ZMConfig::get('console_color')) === false ? [] : $o
);
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai";
$timezone = ZMConfig::get('global', 'timezone') ?? 'Asia/Shanghai';
date_default_timezone_set($timezone);
$list = ModuleManager::getPackedModules();
if (!isset($list[$input->getArgument("module-name")])) {
$output->writeln("<error>不存在打包的模块 ".$input->getArgument("module-name")." !</error>");
if (!isset($list[$input->getArgument('module-name')])) {
$output->writeln('<error>不存在打包的模块 ' . $input->getArgument('module-name') . ' !</error>');
return 1;
}
$result = ModuleManager::unpackModule($list[$input->getArgument("module-name")], $input->getOptions());
if ($result) Console::success("解压完成!");
else Console::error("解压失败!");
$result = ModuleManager::unpackModule($list[$input->getArgument('module-name')], $input->getOptions());
if ($result) {
Console::success('解压完成!');
} else {
Console::error('解压失败!');
}
return 0;
}
}
}

View File

@@ -1,9 +1,9 @@
<?php
declare(strict_types=1);
namespace ZM\Command;
use Swoole\Atomic;
use Swoole\Http\Request;
use Swoole\Http\Response;
@@ -26,71 +26,74 @@ class PureHttpCommand extends Command
// the name of the command (the part after "bin/console")
protected static $defaultName = 'simple-http-server';
protected function configure() {
$this->setDescription("Run a simple http server | 启动一个简单的文件 HTTP 服务器");
$this->setHelp("直接运行可以启动");
protected function configure()
{
$this->setDescription('Run a simple http server | 启动一个简单的文件 HTTP 服务器');
$this->setHelp('直接运行可以启动');
$this->addArgument('dir', InputArgument::REQUIRED, 'Your directory');
$this->addOption("host", 'H', InputOption::VALUE_REQUIRED, "启动监听地址");
$this->addOption("port", 'P', InputOption::VALUE_REQUIRED, "启动监听地址的端口");
$this->addOption('host', 'H', InputOption::VALUE_REQUIRED, '启动监听地址');
$this->addOption('port', 'P', InputOption::VALUE_REQUIRED, '启动监听地址的端口');
// ...
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$tty_width = explode(" ", trim(exec("stty size")))[1];
protected function execute(InputInterface $input, OutputInterface $output): int
{
$tty_width = explode(' ', trim(exec('stty size')))[1];
if (realpath($input->getArgument('dir') ?? '.') === false) {
$output->writeln("<error>Directory error(" . ($input->getArgument('dir') ?? '.') . "): no such file or directory.</error>");
$output->writeln('<error>Directory error(' . ($input->getArgument('dir') ?? '.') . '): no such file or directory.</error>');
return self::FAILURE;
}
ZMConfig::setDirectory(DataProvider::getSourceRootDir() . '/config');
$global = ZMConfig::get("global");
$host = $input->getOption("host") ?? $global["host"];
$port = $input->getOption("port") ?? $global["port"];
$global = ZMConfig::get('global');
$host = $input->getOption('host') ?? $global['host'];
$port = $input->getOption('port') ?? $global['port'];
$index = ["index.html", "index.htm"];
$index = ['index.html', 'index.htm'];
$out = [
"listen" => $host.":".$port,
"version" => ZM_VERSION,
"web_root" => realpath($input->getArgument('dir') ?? '.'),
"index" => implode(",", $index)
'listen' => $host . ':' . $port,
'version' => ZM_VERSION,
'web_root' => realpath($input->getArgument('dir') ?? '.'),
'index' => implode(',', $index),
];
Framework::printProps($out, $tty_width);
$server = new Server($host, $port);
$server->set(ZMConfig::get("global", "swoole"));
$server->set(ZMConfig::get('global', 'swoole'));
Console::init(2, $server);
ZMAtomic::$atomics["request"] = [];
ZMAtomic::$atomics['request'] = [];
for ($i = 0; $i < 32; ++$i) {
ZMAtomic::$atomics["request"][$i] = new Atomic(0);
ZMAtomic::$atomics['request'][$i] = new Atomic(0);
}
$server->on("request", function (Request $request, Response $response) use ($input, $index, $server) {
ZMAtomic::$atomics["request"][$server->worker_id]->add(1);
$server->on('request', function (Request $request, Response $response) use ($input, $index, $server) {
ZMAtomic::$atomics['request'][$server->worker_id]->add(1);
HttpUtil::handleStaticPage(
$request->server["request_uri"],
$request->server['request_uri'],
$response,
[
"document_root" => realpath($input->getArgument('dir') ?? '.'),
"document_index" => $index
]);
'document_root' => realpath($input->getArgument('dir') ?? '.'),
'document_index' => $index,
]
);
//echo "\r" . Coroutine::stats()["coroutine_peak_num"];
});
$server->on("start", function ($server) {
$server->on('start', function ($server) {
Process::signal(SIGINT, function () use ($server) {
echo "\r";
Console::warning("Server interrupted by keyboard.");
Console::warning('Server interrupted by keyboard.');
for ($i = 0; $i < 32; ++$i) {
$num = ZMAtomic::$atomics["request"][$i]->get();
if ($num != 0)
echo "[$i]: " . $num . "\n";
$num = ZMAtomic::$atomics['request'][$i]->get();
if ($num != 0) {
echo "[{$i}]: " . $num . "\n";
}
}
$server->shutdown();
$server->stop();
});
Console::success("Server started. Use Ctrl+C to stop.");
Console::success('Server started. Use Ctrl+C to stop.');
});
$server->start();
// return this if there was no problem running the command
// (it's equivalent to returning int(0))
return 0;
// or return this if some error happened during the execution
// (it's equivalent to returning int(1))
// return 1;

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command;
@@ -8,61 +9,63 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Framework;
use ZM\Utils\DataProvider;
class RunServerCommand extends Command
{
protected static $defaultName = 'server';
protected function configure() {
$this->setAliases(['server:start']);
$this->setDefinition([
new InputOption("debug-mode", "D", null, "开启调试模式 (这将关闭协程化)"),
new InputOption("log-debug", null, null, "调整消息等级到debug (log-level=4)"),
new InputOption("log-verbose", null, null, "调整消息等级到verbose (log-level=3)"),
new InputOption("log-info", null, null, "调整消息等级到info (log-level=2)"),
new InputOption("log-warning", null, null, "调整消息等级到warning (log-level=1)"),
new InputOption("log-error", null, null, "调整消息等级到error (log-level=0)"),
new InputOption("log-theme", null, InputOption::VALUE_REQUIRED, "改变终端的主题配色"),
new InputOption("disable-console-input", null, null, "禁止终端输入内容 (废弃)"),
new InputOption("interact", null, null, "打开终端输入"),
new InputOption("remote-terminal", null, null, "启用远程终端配置使用global.php中的"),
new InputOption("disable-coroutine", null, null, "关闭协程Hook"),
new InputOption("daemon", null, null, "以守护进程的方式运行框架"),
new InputOption("worker-num", null, InputOption::VALUE_REQUIRED, "启动框架时运行的 Worker 进程数量"),
new InputOption("task-worker-num", null, InputOption::VALUE_REQUIRED, "启动框架时运行的 TaskWorker 进程数量"),
new InputOption("watch", null, null, "监听 src/ 目录的文件变化并热更新"),
new InputOption("show-php-ver", null, null, "启动时显示PHP和Swoole版本"),
new InputOption("env", null, InputOption::VALUE_REQUIRED, "设置环境类型 (production, development, staging)"),
new InputOption("disable-safe-exit", null, null, "关闭安全退出关闭后按CtrlC时直接杀死进程"),
new InputOption("preview", null, null, "只显示参数,不启动服务器"),
new InputOption("force-load-module", null, InputOption::VALUE_OPTIONAL, "强制打包状态下加载模块(使用英文逗号分割多个)"),
new InputOption("polling-watch", null, null, "强制启用轮询模式监听"),
]);
$this->setDescription("Run zhamao-framework | 启动框架");
$this->setHelp("直接运行可以启动");
public static function exportDefinition()
{
$cmd = new self();
$cmd->configure();
return $cmd->getDefinition();
}
protected function execute(InputInterface $input, OutputInterface $output): int {
if (($opt = $input->getOption("env")) !== null) {
if (!in_array($opt, ["production", "staging", "development", ""])) {
$output->writeln("<error> \"--env\" option only accept production, development, staging and [empty] ! </error>");
protected function configure()
{
$this->setAliases(['server:start']);
$this->setDefinition([
new InputOption('debug-mode', 'D', null, '开启调试模式 (这将关闭协程化)'),
new InputOption('log-debug', null, null, '调整消息等级到debug (log-level=4)'),
new InputOption('log-verbose', null, null, '调整消息等级到verbose (log-level=3)'),
new InputOption('log-info', null, null, '调整消息等级到info (log-level=2)'),
new InputOption('log-warning', null, null, '调整消息等级到warning (log-level=1)'),
new InputOption('log-error', null, null, '调整消息等级到error (log-level=0)'),
new InputOption('log-theme', null, InputOption::VALUE_REQUIRED, '改变终端的主题配色'),
new InputOption('disable-console-input', null, null, '禁止终端输入内容 (废弃)'),
new InputOption('interact', null, null, '打开终端输入'),
new InputOption('remote-terminal', null, null, '启用远程终端配置使用global.php中的'),
new InputOption('disable-coroutine', null, null, '关闭协程Hook'),
new InputOption('daemon', null, null, '以守护进程的方式运行框架'),
new InputOption('worker-num', null, InputOption::VALUE_REQUIRED, '启动框架时运行的 Worker 进程数量'),
new InputOption('task-worker-num', null, InputOption::VALUE_REQUIRED, '启动框架时运行的 TaskWorker 进程数量'),
new InputOption('watch', null, null, '监听 src/ 目录的文件变化并热更新'),
new InputOption('show-php-ver', null, null, '启动时显示PHP和Swoole版本'),
new InputOption('env', null, InputOption::VALUE_REQUIRED, '设置环境类型 (production, development, staging)'),
new InputOption('disable-safe-exit', null, null, '关闭安全退出关闭后按CtrlC时直接杀死进程'),
new InputOption('preview', null, null, '只显示参数,不启动服务器'),
new InputOption('force-load-module', null, InputOption::VALUE_OPTIONAL, '强制打包状态下加载模块(使用英文逗号分割多个)'),
new InputOption('polling-watch', null, null, '强制启用轮询模式监听'),
]);
$this->setDescription('Run zhamao-framework | 启动框架');
$this->setHelp('直接运行可以启动');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (($opt = $input->getOption('env')) !== null) {
if (!in_array($opt, ['production', 'staging', 'development', ''])) {
$output->writeln('<error> "--env" option only accept production, development, staging and [empty] ! </error>');
return 1;
}
}
$state = Framework::getProcessState(ZM_PROCESS_MASTER);
if (is_array($state) && posix_getsid($state['pid'] ?? -1) !== false) {
$output->writeln("<error>检测到已经在 pid: {$state['pid']} 进程启动了框架!</error>");
$output->writeln("<error>不可以同时启动两个框架!</error>");
$output->writeln('<error>不可以同时启动两个框架!</error>');
return 1;
}
(new Framework($input->getOptions()))->start();
return 0;
}
public static function exportDefinition() {
$cmd = new self();
$cmd->configure();
return $cmd->getDefinition();
}
}

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Server;
@@ -12,14 +13,16 @@ class ServerReloadCommand extends DaemonCommand
{
protected static $defaultName = 'server:reload';
protected function configure() {
$this->setDescription("重载框架");
protected function configure()
{
$this->setDescription('重载框架');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);
Process::kill(intval($this->daemon_file["pid"]), SIGUSR1);
$output->writeln("<info>成功重载!</info>");
Process::kill(intval($this->daemon_file['pid']), SIGUSR1);
$output->writeln('<info>成功重载!</info>');
return 0;
}
}

View File

@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Server;
use Symfony\Component\Console\Input\InputInterface;
@@ -10,25 +12,25 @@ class ServerStatusCommand extends DaemonCommand
{
protected static $defaultName = 'server:status';
protected function configure() {
$this->setDescription("查看框架的运行状态");
protected function configure()
{
$this->setDescription('查看框架的运行状态');
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
parent::execute($input, $output);
$output->writeln("<info>框架" . ($this->daemon_file["daemon"] ? "以守护进程模式" : "") . "运行中pid" . $this->daemon_file["pid"] . "</info>");
if ($this->daemon_file["daemon"]) {
$output->writeln("<comment>----- 以下是stdout内容 -----</comment>");
$stdout = file_get_contents($this->daemon_file["stdout"]);
$output->writeln('<info>框架' . ($this->daemon_file['daemon'] ? '以守护进程模式' : '') . '运行中pid' . $this->daemon_file['pid'] . '</info>');
if ($this->daemon_file['daemon']) {
$output->writeln('<comment>----- 以下是stdout内容 -----</comment>');
$stdout = file_get_contents($this->daemon_file['stdout']);
$stdout = explode("\n", $stdout);
for ($i = 15; $i > 0; --$i) {
if (isset($stdout[count($stdout) - $i]))
if (isset($stdout[count($stdout) - $i])) {
echo $stdout[count($stdout) - $i] . PHP_EOL;
}
}
}
return 0;
}
}
{
}

View File

@@ -1,5 +1,6 @@
<?php
declare(strict_types=1);
namespace ZM\Command\Server;
@@ -15,42 +16,44 @@ class ServerStopCommand extends DaemonCommand
{
protected static $defaultName = 'server:stop';
protected function configure() {
$this->setDescription("停止运行的框架");
protected function configure()
{
$this->setDescription('停止运行的框架');
$this->setDefinition([
new InputOption('force', 'f', InputOption::VALUE_NONE, '强制停止'),
]);
}
protected function execute(InputInterface $input, OutputInterface $output): int {
protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($input->getOption('force') !== false) {
$file_path = _zm_pid_dir();
$list = DataProvider::scanDirFiles($file_path, false, true);
foreach($list as $file) {
foreach ($list as $file) {
$name = explode('.', $file);
if (end($name) == 'pid') {
$pid = file_get_contents($file_path.'/'.$file);
$pid = file_get_contents($file_path . '/' . $file);
Process::kill($pid, SIGKILL);
} elseif ($file === 'master.json') {
$json = json_decode(file_get_contents($file_path.'/'.$file), true);
$json = json_decode(file_get_contents($file_path . '/' . $file), true);
Process::kill($json['pid'], SIGKILL);
}
unlink($file_path.'/'.$file);
unlink($file_path . '/' . $file);
}
} else {
parent::execute($input, $output);
}
Process::kill(intval($this->daemon_file["pid"]), SIGTERM);
Process::kill(intval($this->daemon_file['pid']), SIGTERM);
$i = 10;
while (Framework::getProcessState(ZM_PROCESS_MASTER) !== false && $i > 0) {
sleep(1);
--$i;
}
if ($i === 0) {
$output->writeln("<error>停止失败请检查进程pid #" . $this->daemon_file["pid"] . " 是否响应!</error>");
$output->writeln("<error>或者可以尝试使用参数 --force 来强行杀死所有进程</error>");
$output->writeln('<error>停止失败请检查进程pid #' . $this->daemon_file['pid'] . ' 是否响应!</error>');
$output->writeln('<error>或者可以尝试使用参数 --force 来强行杀死所有进程</error>');
} else {
$output->writeln("<info>成功停止!</info>");
$output->writeln('<info>成功停止!</info>');
}
return 0;
}