merge framework and kernel

This commit is contained in:
sunxyw 2023-03-07 23:07:52 +08:00
parent 8f43012a5c
commit 772288b517
No known key found for this signature in database
GPG Key ID: F391C42B19AFFC98
19 changed files with 153 additions and 176 deletions

View File

@ -57,14 +57,12 @@ $options['driver'] = 'workerman';
$options['worker-num'] = 1; $options['worker-num'] = 1;
$options['private-mode'] = true; $options['private-mode'] = true;
$kernel = \ZM\Kernel::getInstance();
$kernel->setEnvironment('development');
$kernel->setTestMode(true);
$kernel->setConfigDir(dirname(__DIR__) . '/config');
$kernel->bootstrap();
try { try {
(new Framework($options))->init()->start(); $framework = (new Framework($options));
$framework->setEnvironment('development');
$framework->setConfigDir(dirname(__DIR__) . '/config');
$framework->bootstrap();
$framework->init()->start();
exit($_swoole_atomic->get()); exit($_swoole_atomic->get());
} catch (Throwable $e) { } catch (Throwable $e) {
echo $e->getMessage() . PHP_EOL; echo $e->getMessage() . PHP_EOL;

View File

@ -8,7 +8,7 @@ use Psr\Log\LoggerInterface;
use ZM\Config\Environment; use ZM\Config\Environment;
use ZM\Config\EnvironmentInterface; use ZM\Config\EnvironmentInterface;
use ZM\Framework; use ZM\Framework;
use ZM\Kernel; use ZM\HasRuntimeInfo;
/* /*
* 这里是容器的配置文件,你可以在这里配置容器的绑定和其他一些参数。 * 这里是容器的配置文件,你可以在这里配置容器的绑定和其他一些参数。
@ -28,6 +28,8 @@ return [
Driver::class => fn () => Framework::getInstance()->getDriver(), Driver::class => fn () => Framework::getInstance()->getDriver(),
LoggerInterface::class => fn () => logger(), LoggerInterface::class => fn () => logger(),
EnvironmentInterface::class => Environment::class, EnvironmentInterface::class => Environment::class,
HasRuntimeInfo::class => Framework::class,
], ],
// 容器的缓存配置,默认情况下,只有在生产环境下才会启用缓存 // 容器的缓存配置,默认情况下,只有在生产环境下才会启用缓存
@ -37,7 +39,7 @@ return [
// 详细介绍请参阅https://php-di.org/doc/performances.html#caching // 详细介绍请参阅https://php-di.org/doc/performances.html#caching
'cache' => [ 'cache' => [
// 是否启用缓存,支持 bool、callable // 是否启用缓存,支持 bool、callable
'enable' => fn () => Kernel::getInstance()->environment('production'), 'enable' => fn () => Framework::getInstance()->environment('production'),
'namespace' => 'zm', 'namespace' => 'zm',
], ],
]; ];

View File

@ -28,6 +28,6 @@
</report> </report>
</coverage> </coverage>
<php> <php>
<env name="APP_ENV" value="testing"/> <env name="PHPUNIT_RUNNING" value="1"/>
</php> </php>
</phpunit> </phpunit>

View File

@ -4,9 +4,9 @@ declare(strict_types=1);
namespace ZM\Bootstrap; namespace ZM\Bootstrap;
use ZM\Kernel; use ZM\HasRuntimeInfo;
interface Bootstrapper interface Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void; public function bootstrap(HasRuntimeInfo $runtime_info): void;
} }

View File

@ -6,11 +6,11 @@ namespace ZM\Bootstrap;
use OneBot\Exception\ExceptionHandler; use OneBot\Exception\ExceptionHandler;
use ZM\Exception\Handler; use ZM\Exception\Handler;
use ZM\Kernel; use ZM\HasRuntimeInfo;
class HandleExceptions implements Bootstrapper class HandleExceptions implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
// 注册全局错误处理器 // 注册全局错误处理器
set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) { set_error_handler(function ($error_no, $error_msg, $error_file, $error_line) {

View File

@ -8,11 +8,11 @@ use Dotenv\Dotenv;
use ZM\Config\Environment; use ZM\Config\Environment;
use ZM\Config\EnvironmentInterface; use ZM\Config\EnvironmentInterface;
use ZM\Config\ZMConfig; use ZM\Config\ZMConfig;
use ZM\Kernel; use ZM\HasRuntimeInfo;
class LoadConfiguration implements Bootstrapper class LoadConfiguration implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
// TODO: 重新思考容器绑定的加载方式,从而在此处使用 interface // TODO: 重新思考容器绑定的加载方式,从而在此处使用 interface
$env = resolve(Environment::class); $env = resolve(Environment::class);
@ -20,7 +20,7 @@ class LoadConfiguration implements Bootstrapper
new ZMConfig([ new ZMConfig([
'source' => [ 'source' => [
'paths' => [$kernel->getConfigDir()], 'paths' => [$runtime_info->getConfigDir()],
], ],
]); ]);
} }

View File

@ -4,11 +4,11 @@ declare(strict_types=1);
namespace ZM\Bootstrap; namespace ZM\Bootstrap;
use ZM\Kernel; use ZM\HasRuntimeInfo;
class LoadGlobalDefines implements Bootstrapper class LoadGlobalDefines implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
require FRAMEWORK_ROOT_DIR . '/src/Globals/global_defines_framework.php'; require FRAMEWORK_ROOT_DIR . '/src/Globals/global_defines_framework.php';
} }

View File

@ -4,12 +4,12 @@ declare(strict_types=1);
namespace ZM\Bootstrap; namespace ZM\Bootstrap;
use ZM\Kernel; use ZM\HasRuntimeInfo;
use ZM\Plugin\PluginManager; use ZM\Plugin\PluginManager;
class LoadPlugins implements Bootstrapper class LoadPlugins implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
// 先遍历下插件目录下是否有这个插件,没有这个插件则不能打包 // 先遍历下插件目录下是否有这个插件,没有这个插件则不能打包
$plugin_dir = config('global.plugin.load_dir', SOURCE_ROOT_DIR . '/plugins'); $plugin_dir = config('global.plugin.load_dir', SOURCE_ROOT_DIR . '/plugins');

View File

@ -5,11 +5,11 @@ declare(strict_types=1);
namespace ZM\Bootstrap; namespace ZM\Bootstrap;
use ZM\Event\EventProvider; use ZM\Event\EventProvider;
use ZM\Kernel; use ZM\HasRuntimeInfo;
class RegisterEventProvider implements Bootstrapper class RegisterEventProvider implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
global $ob_event_provider; global $ob_event_provider;
$ob_event_provider = EventProvider::getInstance(); $ob_event_provider = EventProvider::getInstance();

View File

@ -4,17 +4,17 @@ declare(strict_types=1);
namespace ZM\Bootstrap; namespace ZM\Bootstrap;
use ZM\Kernel; use ZM\HasRuntimeInfo;
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
class RegisterLogger implements Bootstrapper class RegisterLogger implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
// 初始化 Logger // 初始化 Logger
if (!ob_logger_registered()) { if (!ob_logger_registered()) {
// 如果没有注册过 Logger那么就初始化一个在启动框架前注册的话就不会初始化了可替换为其他 Logger // 如果没有注册过 Logger那么就初始化一个在启动框架前注册的话就不会初始化了可替换为其他 Logger
$logger = new ConsoleLogger($kernel->getLogLevel()); $logger = new ConsoleLogger($runtime_info->getLogLevel());
ob_logger_register($logger); ob_logger_register($logger);
} }
} }

View File

@ -4,11 +4,11 @@ declare(strict_types=1);
namespace ZM\Bootstrap; namespace ZM\Bootstrap;
use ZM\Kernel; use ZM\HasRuntimeInfo;
class SetInternalTimezone implements Bootstrapper class SetInternalTimezone implements Bootstrapper
{ {
public function bootstrap(Kernel $kernel): void public function bootstrap(HasRuntimeInfo $runtime_info): void
{ {
date_default_timezone_set(config('global.runtime.timezone', 'UTC')); date_default_timezone_set(config('global.runtime.timezone', 'UTC'));
} }

View File

@ -74,7 +74,7 @@ class ServerStartCommand extends ServerCommand
} }
// 框架启动的入口 // 框架启动的入口
(new Framework($input->getOptions()))->init()->start(); Framework::getInstance()->init($input->getOptions())->start();
return 0; return 0;
} }
} }

View File

@ -8,7 +8,7 @@ use OneBot\Config\Config;
use OneBot\Config\Loader\LoaderInterface; use OneBot\Config\Loader\LoaderInterface;
use OneBot\Util\Singleton; use OneBot\Util\Singleton;
use ZM\Exception\ConfigException; use ZM\Exception\ConfigException;
use ZM\Kernel; use ZM\Framework;
class ZMConfig class ZMConfig
{ {
@ -302,7 +302,7 @@ class ZMConfig
} }
if ($type === 'environment') { if ($type === 'environment') {
$name_and_env = explode('.', $name); $name_and_env = explode('.', $name);
if (Kernel::getInstance()->environment($name_and_env[1])) { if (Framework::getInstance()->environment($name_and_env[1])) {
return true; return true;
} }
} }

View File

@ -52,8 +52,8 @@ final class ConsoleApplication extends Application
$input = $event->getInput(); $input = $event->getInput();
// 初始化内核 // 初始化内核
/** @var Kernel $kernel */ /** @var Framework $kernel */
$kernel = Kernel::getInstance(); $kernel = Framework::getInstance();
$kernel->setConfigDir($input->getOption('config-dir')); $kernel->setConfigDir($input->getOption('config-dir'));
$kernel->setEnvironment($input->getOption('env')); $kernel->setEnvironment($input->getOption('env'));
$kernel->setDebugMode($input->getOption('debug')); $kernel->setDebugMode($input->getOption('debug'));

View File

@ -8,7 +8,7 @@ use DI;
use DI\Container; use DI\Container;
use DI\ContainerBuilder; use DI\ContainerBuilder;
use OneBot\Driver\Coroutine\Adaptive; use OneBot\Driver\Coroutine\Adaptive;
use ZM\Kernel; use ZM\Framework;
class ContainerHolder class ContainerHolder
{ {
@ -66,6 +66,6 @@ class ContainerHolder
if (self::$config) { if (self::$config) {
return; return;
} }
self::$config = require Kernel::getInstance()->getConfigDir() . '/container.php'; self::$config = require Framework::getInstance()->getConfigDir() . '/container.php';
} }
} }

View File

@ -20,6 +20,7 @@ use OneBot\Driver\Swoole\SwooleDriver;
use OneBot\Driver\Workerman\Worker; use OneBot\Driver\Workerman\Worker;
use OneBot\Driver\Workerman\WorkermanDriver; use OneBot\Driver\Workerman\WorkermanDriver;
use OneBot\Util\Singleton; use OneBot\Util\Singleton;
use ZM\Bootstrap\Bootstrapper;
use ZM\Command\Server\ServerStartCommand; use ZM\Command\Server\ServerStartCommand;
use ZM\Container\ContainerBindingListener; use ZM\Container\ContainerBindingListener;
use ZM\Event\Listener\HttpEventListener; use ZM\Event\Listener\HttpEventListener;
@ -38,7 +39,7 @@ use ZM\Utils\EasterEgg;
* 框架入口类 * 框架入口类
* @since 3.0 * @since 3.0
*/ */
class Framework class Framework implements HasRuntimeInfo
{ {
use Singleton; use Singleton;
@ -67,31 +68,40 @@ class Framework
Bootstrap\SetInternalTimezone::class, // 设置时区 Bootstrap\SetInternalTimezone::class, // 设置时区
]; ];
protected string $environment = 'development';
protected bool $debug_mode = false;
protected string $log_level = 'info';
protected string $config_dir = SOURCE_ROOT_DIR . '/config';
/** /**
* 框架初始化文件 * 框架初始化文件
*
* @param array<string, null|bool|string> $argv 传入的参数(见 ServerStartCommand
* @throws \Exception * @throws \Exception
*/ */
public function __construct(array $argv = []) public function __construct()
{ {
// 单例化整个Framework类 // 单例化整个Framework类
if (self::$instance !== null) { if (self::$instance !== null) {
throw new SingletonViolationException(self::class); throw new SingletonViolationException(self::class);
} }
self::$instance = $this; self::$instance = $this;
// 初始化必需的args参数如果没有传入的话使用默认值
$this->argv = empty($argv) ? ServerStartCommand::exportOptionArray() : $argv;
} }
/** /**
* 初始化框架 * 初始化框架
* *
* @param array<string, null|bool|string> $argv 传入的参数(见 ServerStartCommand
*
* @throws \Exception * @throws \Exception
*/ */
public function init(): Framework public function init(array $argv = []): Framework
{ {
// TODO: discard argv
// 初始化必需的args参数如果没有传入的话使用默认值
$this->argv = empty($argv) ? ServerStartCommand::exportOptionArray() : $argv;
// 初始化 @OnSetup 事件 // 初始化 @OnSetup 事件
$this->initSetupAnnotations(); $this->initSetupAnnotations();
@ -250,6 +260,73 @@ class Framework
} }
} }
public function bootstrap(): void
{
foreach ($this->bootstrappers as $bootstrapper) {
/* @var Bootstrapper $bootstrapper */
(new $bootstrapper())->bootstrap($this);
}
}
public function environment(...$environments): string|bool
{
if (empty($environments)) {
return $this->environment;
}
return in_array($this->environment, $environments, true);
}
public function setEnvironment(string $environment): void
{
$this->environment = $environment;
}
public function isDebugMode(): bool
{
return $this->debug_mode;
}
public function setDebugMode(bool $debug_mode): void
{
$this->debug_mode = $debug_mode;
}
public function getLogLevel(): string
{
return $this->isDebugMode() ? 'debug' : $this->log_level;
}
public function setLogLevel(string $log_level): void
{
$this->log_level = $log_level;
}
public function getConfigDir(): string
{
return $this->config_dir;
}
public function setConfigDir(string $config_dir): void
{
$this->config_dir = $config_dir;
}
public function runningInInteractiveTerminal(): bool
{
if (function_exists('posix_isatty')) {
return posix_isatty(STDIN) && posix_isatty(STDOUT);
}
// fallback to stream_isatty() if posix_isatty() is not available (e.g. on Windows)
return function_exists('stream_isatty') && stream_isatty(STDIN) && stream_isatty(STDOUT);
}
public function runningUnitTests(): bool
{
return defined('PHPUNIT_RUNNING') && constant('PHPUNIT_RUNNING');
}
/** /**
* 打印属性表格 * 打印属性表格
*/ */
@ -259,7 +336,7 @@ class Framework
// 打印工作目录 // 打印工作目录
$properties['working_dir'] = WORKING_DIR; $properties['working_dir'] = WORKING_DIR;
// 打印环境信息 // 打印环境信息
$properties['environment'] = Kernel::getInstance()->environment(); $properties['environment'] = $this->environment();
// 打印驱动 // 打印驱动
$properties['driver'] = config('global.driver'); $properties['driver'] = config('global.driver');
// 打印logger显示等级 // 打印logger显示等级

31
src/ZM/HasRuntimeInfo.php Normal file
View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace ZM;
interface HasRuntimeInfo
{
/**
* 是否正在可交互終端中运行
*/
public function runningInInteractiveTerminal(): bool;
/**
* 是否正执行单元测试
*/
public function runningUnitTests(): bool;
/**
* 获取或检查运行环境
*
* @param array|string ...$environments
*/
public function environment(...$environments): string|bool;
public function isDebugMode(): bool;
public function getLogLevel(): string;
public function getConfigDir(): string;
}

View File

@ -1,131 +0,0 @@
<?php
declare(strict_types=1);
namespace ZM;
use OneBot\Util\Singleton;
use ZM\Bootstrap\Bootstrapper;
class Kernel
{
use Singleton;
private array $bootstrappers = [];
private string $config_dir = SOURCE_ROOT_DIR . '/config';
private string $environment = 'development';
private bool $debug_mode = false;
private string $log_level = 'info';
private bool $test_mode = false;
private function __construct()
{
$this->registerBootstrappers([
Bootstrap\LoadConfiguration::class, // 加载配置文件
Bootstrap\LoadGlobalDefines::class, // 加载框架级别的全局常量声明
Bootstrap\RegisterLogger::class, // 加载 Logger
Bootstrap\HandleExceptions::class, // 注册异常处理器
Bootstrap\RegisterEventProvider::class, // 绑定框架的 EventProvider 到 libob 的 Driver 上
Bootstrap\SetInternalTimezone::class, // 设置时区
]);
}
/**
* 获取版本号
*/
public function version(): string
{
return ZM_VERSION;
}
/**
* 获取配置文件目录
*/
public function getConfigDir(): string
{
return $this->config_dir;
}
/**
* 设置配置文件目录
*/
public function setConfigDir(string $config_dir): void
{
$this->config_dir = $config_dir;
}
/**
* 获取或检查运行环境
*
* @param array|string ...$environments
*/
public function environment(...$environments): string|bool
{
if (empty($environments)) {
return $this->environment;
}
return in_array($this->environment, $environments, true);
}
/**
* 设置运行环境
*/
public function setEnvironment(string $environment): void
{
$this->environment = $environment;
}
public function isDebugMode(): bool
{
return $this->debug_mode;
}
public function setDebugMode(bool $debug_mode): void
{
$this->debug_mode = $debug_mode;
}
public function getLogLevel(): string
{
return $this->isDebugMode() ? 'debug' : $this->log_level;
}
public function setLogLevel(string $log_level): void
{
$this->log_level = $log_level;
}
public function runningInConsole(): bool
{
return PHP_SAPI === 'cli';
}
public function runningUnitTests(): bool
{
return $this->test_mode;
}
public function setTestMode(bool $test_mode): void
{
$this->test_mode = $test_mode;
}
public function registerBootstrappers(array $bootstrappers): void
{
$this->bootstrappers = array_merge($this->bootstrappers, $bootstrappers);
}
public function bootstrap(): void
{
foreach ($this->bootstrappers as $bootstrapper) {
/* @var Bootstrapper $bootstrapper */
(new $bootstrapper())->bootstrap($this);
}
}
}

View File

@ -53,6 +53,6 @@ class ZMApplication extends ZMPlugin
$meta = new PluginMeta(name: 'native', plugin_type: ZM_PLUGIN_TYPE_NATIVE); $meta = new PluginMeta(name: 'native', plugin_type: ZM_PLUGIN_TYPE_NATIVE);
$meta->bindEntity($this); $meta->bindEntity($this);
PluginManager::addPlugin($meta); PluginManager::addPlugin($meta);
(new Framework($this->args))->init()->start(); Framework::getInstance()->init($this->args)->start();
} }
} }