提交 0803a1fe 编写于 作者: W wolfcode

update Core && fix bug

上级 3eb27bc2
......@@ -50,19 +50,20 @@ class InstallCheck implements MiddlewareInterface
try {
$conn = mysqli_connect($dbHost, $dbUser, $dbPwd, null, $dbPort);
mysqli_query($conn, "SET NAMES {$dbCharset}");
$initDb = mysqli_select_db($conn, $dbName);
if (!$initDb) {
try {
mysqli_select_db($conn, $dbName);
} catch (\mysqli_sql_exception $exception) {
if (!mysqli_query($conn, "CREATE DATABASE IF NOT EXISTS `{$dbName}` DEFAULT CHARACTER SET {$dbCharset};")) {
$errorMsg = "数据库{$dbName} 不存在,也没权限创建新的数据库!";
mysqli_close($conn);
return response($errorMsg, 400);
}
mysqli_select_db($conn, $dbName);
}
// 先建表
$db_data = file_get_contents($db_base_data);
$sqlFormat = sql_split($db_data);
$counts = count($sqlFormat);
mysqli_select_db($conn, $dbName);
for ($index = 0; $index < $counts; $index++) {
$sql = trim($sqlFormat[$index]);
if (strstr($sql, 'CREATE TABLE')) {
......@@ -79,7 +80,7 @@ class InstallCheck implements MiddlewareInterface
mysqli_close($conn);
@touch($lock_file);
return $handler($request);
} catch (\Exception $e) {
} catch (\Throwable $e) {
$errorMsg = "连接 MySQL 失败: " . mysqli_connect_error() . $e->getMessage();
return response($errorMsg, 400);
}
......
......@@ -25,7 +25,7 @@
},
"require": {
"php": ">=7.2",
"workerman/webman-framework": "^1.3.0",
"workerman/webman-framework": "1.4.3",
"monolog/monolog": "^2.0",
"webman/auto-route": "^1.0",
"webman/think-orm": "1.0.2",
......@@ -40,7 +40,8 @@
"webman/think-cache": "^1.0",
"aliyuncs/oss-sdk-php": "^2.4",
"qcloud/cos-sdk-v5": "^2.5",
"jasongrimes/paginator": "^1.0"
"jasongrimes/paginator": "^1.0",
"webman/console": "1.0.27"
},
"suggest": {
"ext-event": "For better performance. "
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "02d0c65ff3d87ccf79b24943c0ba01d7",
"content-hash": "1e7532d2b14481835ed4cafcfb0c520b",
"packages": [
{
"name": "aliyuncs/oss-sdk-php",
......@@ -3634,6 +3634,58 @@
},
"time": "2022-04-01T07:37:43+00:00"
},
{
"name": "webman/console",
"version": "v1.0.27",
"source": {
"type": "git",
"url": "https://github.com/webman-php/console.git",
"reference": "e450967eaabc43eb0c93cfcd6d8f420c16e22b67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/console/zipball/e450967eaabc43eb0c93cfcd6d8f420c16e22b67",
"reference": "e450967eaabc43eb0c93cfcd6d8f420c16e22b67",
"shasum": ""
},
"require": {
"symfony/console": ">=5.0"
},
"require-dev": {
"workerman/webman": "^1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Webman\\Console\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "walkor",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net",
"role": "Developer"
}
],
"description": "Webman console",
"homepage": "http://www.workerman.net",
"keywords": [
"webman console"
],
"support": {
"email": "walkor@workerman.net",
"forum": "http://www.workerman.net/questions",
"issues": "https://github.com/webman-php/console/issues",
"source": "https://github.com/webman-php/console",
"wiki": "http://www.workerman.net/doc/webman"
},
"time": "2022-07-01T08:59:02+00:00"
},
{
"name": "webman/think-cache",
"version": "v1.0.1",
......@@ -3771,16 +3823,16 @@
},
{
"name": "workerman/webman-framework",
"version": "v1.3.12",
"version": "v1.4.3",
"source": {
"type": "git",
"url": "https://github.com/walkor/webman-framework.git",
"reference": "a5b392e68a88993e2c94f73805630458b6058c01"
"reference": "0f4d5b6c58823656bdc9603f762d4be6e41ae380"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/a5b392e68a88993e2c94f73805630458b6058c01",
"reference": "a5b392e68a88993e2c94f73805630458b6058c01",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/0f4d5b6c58823656bdc9603f762d4be6e41ae380",
"reference": "0f4d5b6c58823656bdc9603f762d4be6e41ae380",
"shasum": ""
},
"require": {
......@@ -3838,7 +3890,7 @@
"type": "patreon"
}
],
"time": "2022-04-28T12:25:46+00:00"
"time": "2022-08-15T12:35:14+00:00"
},
{
"name": "workerman/workerman",
......
<?php
return [
'enable' => true,
'phar_file_output_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
'phar_filename' => 'webman.phar',
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
//'exclude_pattern' => '#^(?!.*(config/plugin/webman/console/app.php|webman/console/src/Commands/(PharPackCommand.php|ReloadCommand.php)|LICENSE|composer.json|.github|.idea|doc|docs|.git|.setting|runtime|test|test_old|tests|Tests|vendor-bin|.md))(.*)$#',
'exclude_files' => [
'.env', 'LICENSE', 'composer.json', 'composer.lock','start.php'
]
];
此差异已折叠。
#!/usr/bin/env php
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use Workerman\Protocols\Http;
use Workerman\Connection\TcpConnection;
use Webman\App;
use Webman\Config;
use Webman\Route;
use Webman\Middleware;
use Dotenv\Dotenv;
use support\Request;
use support\Log;
use support\Container;
ini_set('display_errors', 'on');
error_reporting(E_ALL);
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
Dotenv::createUnsafeImmutable(base_path())->load();
} else {
Dotenv::createMutable(base_path())->load();
}
}
Config::load(config_path(), ['route', 'container']);
if ($timezone = config('app.default_timezone')) {
date_default_timezone_set($timezone);
}
$runtime_logs_path = runtime_path() . DIRECTORY_SEPARATOR . 'logs';
if ( !file_exists($runtime_logs_path) || !is_dir($runtime_logs_path) ) {
if (!mkdir($runtime_logs_path,0777,true)) {
throw new \RuntimeException("Failed to create runtime logs directory. Please check the permission.");
}
}
$runtime_views_path = runtime_path() . DIRECTORY_SEPARATOR . 'views';
if ( !file_exists($runtime_views_path) || !is_dir($runtime_views_path) ) {
if (!mkdir($runtime_views_path,0777,true)) {
throw new \RuntimeException("Failed to create runtime views directory. Please check the permission.");
}
}
Worker::$onMasterReload = function () {
if (function_exists('opcache_get_status')) {
if ($status = opcache_get_status()) {
if (isset($status['scripts']) && $scripts = $status['scripts']) {
foreach (array_keys($scripts) as $file) {
opcache_invalidate($file, true);
}
}
}
}
};
$config = config('server');
Worker::$pidFile = $config['pid_file'];
Worker::$stdoutFile = $config['stdout_file'];
Worker::$logFile = $config['log_file'];
Worker::$eventLoopClass = $config['event_loop'] ?? '';
TcpConnection::$defaultMaxPackageSize = $config['max_package_size'] ?? 10 * 1024 * 1024;
if (property_exists(Worker::class, 'statusFile')) {
Worker::$statusFile = $config['status_file'] ?? '';
}
if (property_exists(Worker::class, 'stopTimeout')) {
Worker::$stopTimeout = $config['stop_timeout'] ?? 2;
}
if ($config['listen']) {
$worker = new Worker($config['listen'], $config['context']);
$property_map = [
'name',
'count',
'user',
'group',
'reusePort',
'transport',
'protocol'
];
foreach ($property_map as $property) {
if (isset($config[$property])) {
$worker->$property = $config[$property];
}
}
$worker->onWorkerStart = function ($worker) {
require_once base_path() . '/support/bootstrap.php';
$app = new App($worker, Container::instance(), Log::channel('default'), app_path(), public_path());
Http::requestClass(config('app.request_class', config('server.request_class', Request::class)));
$worker->onMessage = [$app, 'onMessage'];
};
}
// Windows does not support custom processes.
if (\DIRECTORY_SEPARATOR === '/') {
foreach (config('process', []) as $process_name => $config) {
worker_start($process_name, $config);
}
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
foreach ($project['process'] ?? [] as $process_name => $config) {
worker_start("plugin.$firm.$name.$process_name", $config);
}
}
}
}
Worker::runAll();
Support\App::run();
......@@ -13,10 +13,12 @@
*/
use Dotenv\Dotenv;
use support\Container;
use support\Log;
use Webman\Bootstrap;
use Webman\Config;
use Webman\Route;
use Webman\Middleware;
use Webman\Util;
$worker = $worker ?? null;
......@@ -24,7 +26,7 @@ if ($timezone = config('app.default_timezone')) {
date_default_timezone_set($timezone);
}
set_error_handler(function ($level, $message, $file = '', $line = 0, $context = []) {
set_error_handler(function ($level, $message, $file = '', $line = 0) {
if (error_reporting() & $level) {
throw new ErrorException($message, 0, $level, $file, $line);
}
......@@ -46,45 +48,85 @@ if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
}
}
Config::reload(config_path(), ['route', 'container']);
Support\App::loadAllConfig(['route']);
foreach (config('autoload.files', []) as $file) {
include_once $file;
}
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
if (!is_array($project)) {
continue;
}
foreach ($project['autoload']['files'] ?? [] as $file) {
include_once $file;
}
}
foreach ($projects['autoload']['files'] ?? [] as $file) {
include_once $file;
}
}
foreach (config('autoload.files', []) as $file) {
include_once $file;
}
$container = Container::instance();
Route::container($container);
Middleware::container($container);
Middleware::load(config('middleware', []));
Middleware::load(config('middleware', []), '');
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
Middleware::load($project['middleware'] ?? []);
if (!is_array($project) || $name === 'static') {
continue;
}
Middleware::load($project['middleware'] ?? [], '');
}
Middleware::load($projects['middleware'] ?? [], $firm);
if ($static_middlewares = config("plugin.$firm.static.middleware")) {
Middleware::load(['__static__' => $static_middlewares], $firm);
}
}
Middleware::load(['__static__' => config('static.middleware', [])]);
Middleware::load(['__static__' => config('static.middleware', [])], '');
foreach (config('bootstrap', []) as $class_name) {
/** @var \Webman\Bootstrap $class_name */
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in config/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
}
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
if (!is_array($project)) {
continue;
}
foreach ($project['bootstrap'] ?? [] as $class_name) {
/** @var \Webman\Bootstrap $class_name */
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
}
}
foreach ($projects['bootstrap'] ?? [] as $class_name) {
if (!class_exists($class_name)) {
$log = "Warning: Class $class_name setting in plugin/$firm/config/bootstrap.php not found\r\n";
echo $log;
Log::error($log);
continue;
}
/** @var Bootstrap $class_name */
$class_name::start($worker);
}
}
$directory = base_path() . '/plugin';
$paths = [config_path()];
foreach (Util::scanDir($directory) as $path) {
if (is_dir($path = "$path/config")) {
$paths[] = $path;
}
}
Route::load($paths);
Route::load(config_path());
\ No newline at end of file
......@@ -26,22 +26,22 @@ use Webman\Config;
use Webman\Route;
// Phar support.
if (is_phar()) {
define('BASE_PATH', dirname(__DIR__));
if (\is_phar()) {
\define('BASE_PATH', dirname(__DIR__));
} else {
define('BASE_PATH', realpath(__DIR__ . '/../'));
\define('BASE_PATH', realpath(__DIR__ . '/../'));
}
define('WEBMAN_VERSION', '1.3.0');
\define('WEBMAN_VERSION', '1.4');
/**
* @param $return_phar
* @return false|string
*/
function base_path($return_phar = true)
function base_path(bool $return_phar = true)
{
static $real_path = '';
if (!$real_path) {
$real_path = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
$real_path = \is_phar() ? \dirname(Phar::running(false)) : BASE_PATH;
}
return $return_phar ? BASE_PATH : $real_path;
}
......@@ -61,7 +61,7 @@ function public_path()
{
static $path = '';
if (!$path) {
$path = get_realpath(config('app.public_path', BASE_PATH . DIRECTORY_SEPARATOR . 'public'));
$path = \config('app.public_path', BASE_PATH . DIRECTORY_SEPARATOR . 'public');
}
return $path;
}
......@@ -84,30 +84,30 @@ function runtime_path()
{
static $path = '';
if (!$path) {
$path = get_realpath(config('app.runtime_path', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime'));
$path = \config('app.runtime_path', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime');
}
return $path;
}
/**
* @param int $status
* @param array $headers
* @param int $status
* @param array $headers
* @param string $body
* @return Response
*/
function response($body = '', $status = 200, $headers = array())
function response($body = '', $status = 200, $headers = [])
{
return new Response($status, $headers, $body);
}
/**
* @param $data
* @param $data
* @param int $options
* @return Response
*/
function json($data, $options = JSON_UNESCAPED_UNICODE)
{
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
return new Response(200, ['Content-Type' => 'application/json'], \json_encode($data, $options));
}
/**
......@@ -123,25 +123,25 @@ function xml($xml)
}
/**
* @param $data
* @param $data
* @param string $callback_name
* @return Response
*/
function jsonp($data, $callback_name = 'callback')
{
if (!is_scalar($data) && null !== $data) {
$data = json_encode($data);
if (!\is_scalar($data) && null !== $data) {
$data = \json_encode($data);
}
return new Response(200, [], "$callback_name($data)");
}
/**
* @param $location
* @param int $status
* @param string $location
* @param int $status
* @param array $headers
* @return Response
*/
function redirect($location, $status = 302, $headers = [])
function redirect(string $location, int $status = 302, array $headers = [])
{
$response = new Response($status, ['Location' => $location]);
if (!empty($headers)) {
......@@ -151,60 +151,60 @@ function redirect($location, $status = 302, $headers = [])
}
/**
* @param $template
* @param $template
* @param array $vars
* @param null $app
* @param null $app
* @return Response
*/
function view($template, $vars = [], $app = null)
function view(string $template, array $vars = [], string $app = null)
{
static $handler;
if (null === $handler) {
$handler = config('view.handler');
}
$request = \request();
$plugin = $request->plugin ?? '';
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
return new Response(200, [], $handler::render($template, $vars, $app));
}
/**
* @param $template
* @param string $template
* @param array $vars
* @param null $app
* @param string|null $app
* @return Response
* @throws Throwable
*/
function raw_view($template, $vars = [], $app = null)
function raw_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], Raw::render($template, $vars, $app));
}
/**
* @param $template
* @param string $template
* @param array $vars
* @param null $app
* @param string|null $app
* @return Response
*/
function blade_view($template, $vars = [], $app = null)
function blade_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], Blade::render($template, $vars, $app));
}
/**
* @param $template
* @param string $template
* @param array $vars
* @param null $app
* @param string|null $app
* @return Response
*/
function think_view($template, $vars = [], $app = null)
function think_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
}
/**
* @param $template
* @param string $template
* @param array $vars
* @param null $app
* @param string|null $app
* @return Response
*/
function twig_view($template, $vars = [], $app = null)
function twig_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], Twig::render($template, $vars, $app));
}
......@@ -218,21 +218,21 @@ function request()
}
/**
* @param $key
* @param null $default
* @return mixed
* @param string|null $key
* @param $default
* @return array|mixed|null
*/
function config($key = null, $default = null)
function config(string $key = null, $default = null)
{
return Config::get($key, $default);
}
/**
* @param $name
* @param string $name
* @param ...$parameters
* @return string
*/
function route($name, ...$parameters)
function route(string $name, ...$parameters)
{
$route = Route::getByName($name);
if (!$route) {
......@@ -243,8 +243,8 @@ function route($name, ...$parameters)
return $route->url();
}
if (is_array(current($parameters))) {
$parameters = current($parameters);
if (\is_array(\current($parameters))) {
$parameters = \current($parameters);
}
return $route->url($parameters);
......@@ -257,7 +257,7 @@ function route($name, ...$parameters)
*/
function session($key = null, $default = null)
{
$session = request()->session();
$session = \request()->session();
if (null === $key) {
return $session;
}
......@@ -267,7 +267,7 @@ function session($key = null, $default = null)
}
if (\strpos($key, '.')) {
$key_array = \explode('.', $key);
$value = $session->all();
$value = $session->all();
foreach ($key_array as $index) {
if (!isset($value[$index])) {
return $default;
......@@ -280,8 +280,8 @@ function session($key = null, $default = null)
}
/**
* @param null|string $id
* @param array $parameters
* @param string $id
* @param array $parameters
* @param string|null $domain
* @param string|null $locale
* @return string
......@@ -311,48 +311,50 @@ function locale(string $locale = null)
*/
function not_found()
{
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
return new Response(404, [], \file_get_contents(public_path() . '/404.html'));
}
/**
* Copy dir.
* @param $source
* @param $dest
*
* @param string $source
* @param string $dest
* @param bool $overwrite
* @return void
*/
function copy_dir($source, $dest, $overwrite = false)
function copy_dir(string $source, string $dest, bool $overwrite = false)
{
if (is_dir($source)) {
if (\is_dir($source)) {
if (!is_dir($dest)) {
mkdir($dest);
\mkdir($dest);
}
$files = scandir($source);
$files = \scandir($source);
foreach ($files as $file) {
if ($file !== "." && $file !== "..") {
copy_dir("$source/$file", "$dest/$file");
\copy_dir("$source/$file", "$dest/$file");
}
}
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
copy($source, $dest);
} else if (\file_exists($source) && ($overwrite || !\file_exists($dest))) {
\copy($source, $dest);
}
}
/**
* Remove dir.
* @param $dir
*
* @param string $dir
* @return bool
*/
function remove_dir($dir)
function remove_dir(string $dir)
{
if (is_link($dir) || is_file($dir)) {
return unlink($dir);
if (\is_link($dir) || \is_file($dir)) {
return \unlink($dir);
}
$files = array_diff(scandir($dir), array('.', '..'));
$files = \array_diff(\scandir($dir), array('.', '..'));
foreach ($files as $file) {
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
(\is_dir("$dir/$file") && !\is_link($dir)) ? \remove_dir("$dir/$file") : \unlink("$dir/$file");
}
return rmdir($dir);
return \rmdir($dir);
}
/**
......@@ -369,15 +371,15 @@ function worker_bind($worker, $class)
'onBufferFull',
'onBufferDrain',
'onWorkerStop',
'onWebSocketConnect',
'onWebSocketConnect'
];
foreach ($callback_map as $name) {
if (method_exists($class, $name)) {
if (\method_exists($class, $name)) {
$worker->$name = [$class, $name];
}
}
if (method_exists($class, 'onWorkerStart')) {
call_user_func([$class, 'onWorkerStart'], $worker);
if (\method_exists($class, 'onWorkerStart')) {
[$class, 'onWorkerStart']($worker);
}
}
......@@ -388,7 +390,7 @@ function worker_bind($worker, $class)
*/
function worker_start($process_name, $config)
{
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
$property_map = [
'count',
'user',
......@@ -406,10 +408,10 @@ function worker_start($process_name, $config)
}
$worker->onWorkerStart = function ($worker) use ($config) {
require_once base_path() . '/support/bootstrap.php';
require_once \base_path() . '/support/bootstrap.php';
foreach ($config['services'] ?? [] as $server) {
if (!class_exists($server['handler'])) {
if (!\class_exists($server['handler'])) {
echo "process error: class {$server['handler']} not exists\r\n";
continue;
}
......@@ -418,18 +420,18 @@ function worker_start($process_name, $config)
echo "listen: {$server['listen']}\n";
}
$instance = Container::make($server['handler'], $server['constructor'] ?? []);
worker_bind($listen, $instance);
\worker_bind($listen, $instance);
$listen->listen();
}
if (isset($config['handler'])) {
if (!class_exists($config['handler'])) {
if (!\class_exists($config['handler'])) {
echo "process error: class {$config['handler']} not exists\r\n";
return;
}
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
worker_bind($worker, $instance);
\worker_bind($worker, $instance);
}
};
......@@ -444,10 +446,10 @@ function worker_start($process_name, $config)
*/
function get_realpath(string $file_path): string
{
if (strpos($file_path, 'phar://') === 0) {
if (\strpos($file_path, 'phar://') === 0) {
return $file_path;
} else {
return realpath($file_path);
return \realpath($file_path);
}
}
......@@ -456,7 +458,7 @@ function get_realpath(string $file_path): string
*/
function is_phar()
{
return class_exists(\Phar::class, false) && Phar::running();
return \class_exists(\Phar::class, false) && Phar::running();
}
/**
......@@ -469,26 +471,12 @@ function cpu_count()
return 1;
}
$count = 4;
if (is_callable('shell_exec')) {
if (strtolower(PHP_OS) === 'darwin') {
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
if (\is_callable('shell_exec')) {
if (\strtolower(PHP_OS) === 'darwin') {
$count = (int)\shell_exec('sysctl -n machdep.cpu.core_count');
} else {
$count = (int)shell_exec('nproc');
$count = (int)\shell_exec('nproc');
}
}
return $count > 0 ? $count : 4;
}
if (!function_exists('env')) {
/**
* Gets the value of an environment variable.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
function env(string $key, $default = null)
{
return \Illuminate\Support\Env::get($key, $default);
}
}
\ No newline at end of file
......@@ -2,6 +2,11 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
exit(1);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit403af8cd99d7ed8c6ce0c15ef03b20d0::getLoader();
......@@ -21,12 +21,14 @@ use Composer\Semver\VersionParser;
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
......@@ -37,7 +39,7 @@ class InstalledVersions
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
......@@ -241,7 +243,7 @@ class InstalledVersions
/**
* @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
......@@ -255,7 +257,7 @@ class InstalledVersions
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
......@@ -278,7 +280,7 @@ class InstalledVersions
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
......@@ -301,7 +303,7 @@ class InstalledVersions
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
......@@ -311,7 +313,7 @@ class InstalledVersions
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
......
......@@ -2,7 +2,7 @@
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
......
......@@ -2,26 +2,26 @@
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
'8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
'253c157292f75eb38082b5acb06f3f01' => $vendorDir . '/nikic/fast-route/src/functions.php',
'538ca81a9a966a6716601ecf48f4eaef' => $vendorDir . '/opis/closure/functions.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php',
'72579e7bd17821bb1321b87411366eae' => $vendorDir . '/illuminate/support/helpers.php',
'2df68f9e79c919e2d88506611769ed2e' => $vendorDir . '/respect/stringifier/src/stringify.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
......
......@@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
......
......@@ -2,7 +2,7 @@
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
......@@ -12,6 +12,7 @@ return array(
'Workerman\\' => array($vendorDir . '/workerman/workerman'),
'Webman\\ThinkOrm\\' => array($vendorDir . '/webman/think-orm/src'),
'Webman\\ThinkCache\\' => array($vendorDir . '/webman/think-cache/src'),
'Webman\\Console\\' => array($vendorDir . '/webman/console/src'),
'Webman\\AutoRoute\\' => array($vendorDir . '/webman/auto-route/src'),
'Webman\\ActionHook\\' => array($vendorDir . '/webman/action-hook/src'),
'Webman\\' => array($vendorDir . '/workerman/webman-framework/src'),
......
......@@ -25,38 +25,15 @@ class ComposerAutoloaderInit403af8cd99d7ed8c6ce0c15ef03b20d0
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit403af8cd99d7ed8c6ce0c15ef03b20d0', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit403af8cd99d7ed8c6ce0c15ef03b20d0', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0::getInitializer($loader));
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
$includeFiles = \Composer\Autoload\ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire403af8cd99d7ed8c6ce0c15ef03b20d0($fileIdentifier, $file);
}
......
......@@ -9,20 +9,20 @@ class ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0
public static $files = array (
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
'8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'60799491728b879e74601d83e38b2cad' => __DIR__ . '/..' . '/illuminate/collections/helpers.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
'253c157292f75eb38082b5acb06f3f01' => __DIR__ . '/..' . '/nikic/fast-route/src/functions.php',
'538ca81a9a966a6716601ecf48f4eaef' => __DIR__ . '/..' . '/opis/closure/functions.php',
'0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php',
'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php',
'72579e7bd17821bb1321b87411366eae' => __DIR__ . '/..' . '/illuminate/support/helpers.php',
'2df68f9e79c919e2d88506611769ed2e' => __DIR__ . '/..' . '/respect/stringifier/src/stringify.php',
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
......@@ -48,6 +48,7 @@ class ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0
'Workerman\\' => 10,
'Webman\\ThinkOrm\\' => 16,
'Webman\\ThinkCache\\' => 18,
'Webman\\Console\\' => 15,
'Webman\\AutoRoute\\' => 17,
'Webman\\ActionHook\\' => 18,
'Webman\\' => 7,
......@@ -165,6 +166,10 @@ class ComposerStaticInit403af8cd99d7ed8c6ce0c15ef03b20d0
array (
0 => __DIR__ . '/..' . '/webman/think-cache/src',
),
'Webman\\Console\\' =>
array (
0 => __DIR__ . '/..' . '/webman/console/src',
),
'Webman\\AutoRoute\\' =>
array (
0 => __DIR__ . '/..' . '/webman/auto-route/src',
......
......@@ -3790,6 +3790,61 @@
},
"install-path": "../webman/auto-route"
},
{
"name": "webman/console",
"version": "v1.0.27",
"version_normalized": "1.0.27.0",
"source": {
"type": "git",
"url": "https://github.com/webman-php/console.git",
"reference": "e450967eaabc43eb0c93cfcd6d8f420c16e22b67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webman-php/console/zipball/e450967eaabc43eb0c93cfcd6d8f420c16e22b67",
"reference": "e450967eaabc43eb0c93cfcd6d8f420c16e22b67",
"shasum": ""
},
"require": {
"symfony/console": ">=5.0"
},
"require-dev": {
"workerman/webman": "^1.0"
},
"time": "2022-07-01T08:59:02+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Webman\\Console\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "walkor",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net",
"role": "Developer"
}
],
"description": "Webman console",
"homepage": "http://www.workerman.net",
"keywords": [
"webman console"
],
"support": {
"email": "walkor@workerman.net",
"forum": "http://www.workerman.net/questions",
"issues": "https://github.com/webman-php/console/issues",
"source": "https://github.com/webman-php/console",
"wiki": "http://www.workerman.net/doc/webman"
},
"install-path": "../webman/console"
},
{
"name": "webman/think-cache",
"version": "v1.0.1",
......@@ -3936,17 +3991,17 @@
},
{
"name": "workerman/webman-framework",
"version": "v1.3.12",
"version_normalized": "1.3.12.0",
"version": "v1.4.3",
"version_normalized": "1.4.3.0",
"source": {
"type": "git",
"url": "https://github.com/walkor/webman-framework.git",
"reference": "a5b392e68a88993e2c94f73805630458b6058c01"
"reference": "0f4d5b6c58823656bdc9603f762d4be6e41ae380"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/a5b392e68a88993e2c94f73805630458b6058c01",
"reference": "a5b392e68a88993e2c94f73805630458b6058c01",
"url": "https://api.github.com/repos/walkor/webman-framework/zipball/0f4d5b6c58823656bdc9603f762d4be6e41ae380",
"reference": "0f4d5b6c58823656bdc9603f762d4be6e41ae380",
"shasum": ""
},
"require": {
......@@ -3958,7 +4013,7 @@
"suggest": {
"ext-event": "For better performance. "
},
"time": "2022-04-28T12:25:46+00:00",
"time": "2022-08-15T12:35:14+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
......
此差异已折叠。
build
vendor
.idea
.vscode
.phpunit*
composer.lock
\ No newline at end of file
# console
webman console
https://www.workerman.net/plugin/1
{
"name": "webman/console",
"type": "library",
"keywords": [
"webman console"
],
"homepage": "http://www.workerman.net",
"license": "MIT",
"description": "Webman console",
"authors": [
{
"name": "walkor",
"email": "walkor@workerman.net",
"homepage": "http://www.workerman.net",
"role": "Developer"
}
],
"support": {
"email": "walkor@workerman.net",
"issues": "https://github.com/webman-php/console/issues",
"forum": "http://www.workerman.net/questions",
"wiki": "http://www.workerman.net/doc/webman",
"source": "https://github.com/webman-php/console"
},
"require": {
"symfony/console": ">=5.0"
},
"autoload": {
"psr-4": {
"Webman\\Console\\" : "src"
}
},
"require-dev": {
"workerman/webman": "^1.0"
}
}
<?php
namespace Webman\Console;
use support\Container;
use support\Log;
use support\Request;
use Webman\App;
use Webman\Config;
use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Http;
use Workerman\Worker;
use Dotenv\Dotenv;
ini_set('display_errors', 'on');
error_reporting(E_ALL);
class Application
{
public static function run()
{
$runtime_logs_path = runtime_path() . DIRECTORY_SEPARATOR . 'logs';
if ( !file_exists($runtime_logs_path) || !is_dir($runtime_logs_path) ) {
if (!mkdir($runtime_logs_path,0777,true)) {
throw new \RuntimeException("Failed to create runtime logs directory. Please check the permission.");
}
}
$runtime_views_path = runtime_path() . DIRECTORY_SEPARATOR . 'views';
if ( !file_exists($runtime_views_path) || !is_dir($runtime_views_path) ) {
if (!mkdir($runtime_views_path,0777,true)) {
throw new \RuntimeException("Failed to create runtime views directory. Please check the permission.");
}
}
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
Dotenv::createUnsafeImmutable(base_path())->load();
} else {
Dotenv::createMutable(base_path())->load();
}
}
Config::reload(config_path(), ['route', 'container']);
Worker::$onMasterReload = function (){
if (function_exists('opcache_get_status')) {
if ($status = opcache_get_status()) {
if (isset($status['scripts']) && $scripts = $status['scripts']) {
foreach (array_keys($scripts) as $file) {
opcache_invalidate($file, true);
}
}
}
}
};
$config = config('server');
Worker::$pidFile = $config['pid_file'];
Worker::$stdoutFile = $config['stdout_file'];
Worker::$logFile = $config['log_file'];
Worker::$eventLoopClass = $config['event_loop'] ?? '';
TcpConnection::$defaultMaxPackageSize = $config['max_package_size'] ?? 10*1024*1024;
if (property_exists(Worker::class, 'statusFile')) {
Worker::$statusFile = $config['status_file'] ?? '';
}
if (property_exists(Worker::class, 'stopTimeout')) {
Worker::$stopTimeout = $config['stop_timeout'] ?? 2;
}
if ($config['listen']) {
$worker = new Worker($config['listen'], $config['context']);
$property_map = [
'name',
'count',
'user',
'group',
'reusePort',
'transport',
'protocol'
];
foreach ($property_map as $property) {
if (isset($config[$property])) {
$worker->$property = $config[$property];
}
}
$worker->onWorkerStart = function ($worker) {
require_once base_path() . '/support/bootstrap.php';
$app = new App($worker, Container::instance(), Log::channel('default'), app_path(), public_path());
Http::requestClass(config('app.request_class', config('server.request_class', Request::class)));
$worker->onMessage = [$app, 'onMessage'];
};
}
// Windows does not support custom processes.
if (\DIRECTORY_SEPARATOR === '/') {
foreach (config('process', []) as $process_name => $config) {
// Remove monitor process.
if (class_exists(\Phar::class, false) && \Phar::running() && 'monitor' === $process_name) {
continue;
}
worker_start($process_name, $config);
}
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
foreach ($project['process'] ?? [] as $process_name => $config) {
worker_start("plugin.$firm.$name.$process_name", $config);
}
}
}
}
Worker::runAll();
}
}
<?php
namespace Webman\Console;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command as Commands;
class Command extends Application
{
public function installInternalCommands()
{
$this->installCommands(__DIR__ . '/Commands', 'Webman\Console\Commands');
}
public function installCommands($path, $namspace = 'app\command')
{
$dir_iterator = new \RecursiveDirectoryIterator($path);
$iterator = new \RecursiveIteratorIterator($dir_iterator);
foreach ($iterator as $file) {
if (is_dir($file)) {
continue;
}
$class_name = $namspace.'\\'.basename($file, '.php');
if (!is_a($class_name, Commands::class, true)) {
continue;
}
$this->add(new $class_name);
}
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Webman\Console\Application;
class ConnectionsCommand extends Command
{
protected static $defaultName = 'connections';
protected static $defaultDescription = 'Get worker connections.';
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (\class_exists(\Support\App::class)) {
\Support\App::run();
return self::SUCCESS;
}
Application::run();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class InstallCommand extends Command
{
protected static $defaultName = 'install';
protected static $defaultDescription = 'Execute webman installation script';
/**
* @return void
*/
protected function configure()
{
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln("Execute installation for webman");
$install_function = "\\Webman\\Install::install";
if (is_callable($install_function)) {
$install_function();
return self::SUCCESS;
}
$output->writeln('<error>This command requires webman-framework version >= 1.3.0</error>');
return self::FAILURE;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class MakeBootstrapCommand extends Command
{
protected static $defaultName = 'make:bootstrap';
protected static $defaultDescription = 'Make bootstrap';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Bootstrap name');
$this->addArgument('enable', InputArgument::OPTIONAL, 'Enable or not');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('name');
$enable = in_array($input->getArgument('enable'), ['no', '0', 'false', 'n']) ? false : true;
$output->writeln("Make bootstrap $name");
$name = str_replace('\\', '/', $name);
if (!$bootstrap_str = Util::guessPath(app_path(), 'bootstrap')) {
$bootstrap_str = Util::guessPath(app_path(), 'controller') === 'Controller' ? 'Bootstrap' : 'bootstrap';
}
$upper = $bootstrap_str === 'Bootstrap';
if (!($pos = strrpos($name, '/'))) {
$name = ucfirst($name);
$file = app_path() . "/$bootstrap_str/$name.php";
$namespace = $upper ? 'App\Bootstrap' : 'app\bootstrap';
} else {
if($real_name = Util::guessPath(app_path(), $name)) {
$name = $real_name;
}
if ($upper && !$real_name) {
$name = preg_replace_callback('/\/([a-z])/', function ($matches) {
return '/' . strtoupper($matches[1]);
}, ucfirst($name));
}
$path = "$bootstrap_str/" . substr($upper ? ucfirst($name) : $name, 0, $pos);
$name = ucfirst(substr($name, $pos + 1));
$file = app_path() . "/$path/$name.php";
$namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path);
}
$this->createBootstrap($name, $namespace, $file);
if ($enable) {
$this->addConfig("$namespace\\$name", config_path() . '/bootstrap.php');
}
return self::SUCCESS;
}
/**
* @param $name
* @param $namespace
* @param $file
* @return void
*/
protected function createBootstrap($name, $namespace, $file)
{
$path = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$bootstrap_content = <<<EOF
<?php
namespace $namespace;
use Webman\Bootstrap;
class $name implements Bootstrap
{
public static function start(\$worker)
{
// Is it console environment ?
\$is_console = !\$worker;
if (\$is_console) {
// If you do not want to execute this in console, just return.
return;
}
}
}
EOF;
file_put_contents($file, $bootstrap_content);
}
public function addConfig($class, $config_file)
{
$config = include $config_file;
if(!in_array($class, $config ?? [])) {
$config_file_content = file_get_contents($config_file);
$config_file_content = preg_replace('/\];/', " $class::class,\n];", $config_file_content);
file_put_contents($config_file, $config_file_content);
}
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class MakeCommandCommand extends Command
{
protected static $defaultName = 'make:command';
protected static $defaultDescription = 'Make command';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Command name');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$command = $name = $input->getArgument('name');
$output->writeln("Make command $name");
// make:command 不支持子目录
$name = str_replace(['\\', '/'], '', $name);
if (!$command_str = Util::guessPath(app_path(), 'command')) {
$command_str = Util::guessPath(app_path(), 'controller') === 'Controller' ? 'Command' : 'command';
}
$upper = $command_str === 'Command';
$name = ucfirst($name);
$file = app_path() . "/$command_str/$name.php";
$namespace = $upper ? 'App\Command' : 'app\command';
$this->createCommand($name, $namespace, $file, $command);
return self::SUCCESS;
}
protected function getClassName($name)
{
return preg_replace_callback('/:([a-zA-Z])/', function ($matches) {
return strtoupper($matches[1]);
}, ucfirst($name)) . 'Command';
}
/**
* @param $name
* @param $namespace
* @param $path
* @return void
*/
protected function createCommand($name, $namespace, $file, $command)
{
$path = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$desc = str_replace(':', ' ', $command);
$command_content = <<<EOF
<?php
namespace $namespace;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
class $name extends Command
{
protected static \$defaultName = '$command';
protected static \$defaultDescription = '$desc';
/**
* @return void
*/
protected function configure()
{
\$this->addArgument('name', InputArgument::OPTIONAL, 'Name description');
}
/**
* @param InputInterface \$input
* @param OutputInterface \$output
* @return int
*/
protected function execute(InputInterface \$input, OutputInterface \$output)
{
\$name = \$input->getArgument('name');
\$output->writeln('Hello $command');
return self::SUCCESS;
}
}
EOF;
file_put_contents($file, $command_content);
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class MakeControllerCommand extends Command
{
protected static $defaultName = 'make:controller';
protected static $defaultDescription = 'Make controller';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Controller name');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument('name');
$output->writeln("Make controller $name");
$suffix = config('app.controller_suffix', '');
if ($suffix && !strpos($name, $suffix)) {
$name .= $suffix;
}
$name = str_replace('\\', '/', $name);
if (!($pos = strrpos($name, '/'))) {
$name = ucfirst($name);
$controller_str = Util::guessPath(app_path(), 'controller') ?: 'controller';
$file = app_path() . "/$controller_str/$name.php";
$namespace = $controller_str === 'Controller' ? 'App\Controller' : 'app\controller';
} else {
$name_str = substr($name, 0, $pos);
if($real_name_str = Util::guessPath(app_path(), $name_str)) {
$name_str = $real_name_str;
} else if ($real_section_name = Util::guessPath(app_path(), strstr($name_str, '/', true))) {
$upper = strtolower($real_section_name[0]) !== $real_section_name[0];
} else if ($real_base_controller = Util::guessPath(app_path(), 'controller')) {
$upper = strtolower($real_base_controller[0]) !== $real_base_controller[0];
}
$upper = $upper ?? strtolower($name_str[0]) !== $name_str[0];
if ($upper && !$real_name_str) {
$name_str = preg_replace_callback('/\/([a-z])/', function ($matches) {
return '/' . strtoupper($matches[1]);
}, ucfirst($name_str));
}
$path = "$name_str/" . ($upper ? 'Controller' : 'controller');
$name = ucfirst(substr($name, $pos + 1));
$file = app_path() . "/$path/$name.php";
$namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path);
}
$this->createController($name, $namespace, $file);
return self::SUCCESS;
}
/**
* @param $name
* @param $namespace
* @param $file
* @return void
*/
protected function createController($name, $namespace, $file)
{
$path = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$controller_content = <<<EOF
<?php
namespace $namespace;
use support\Request;
class $name
{
public function index(Request \$request)
{
return response(__CLASS__);
}
}
EOF;
file_put_contents($file, $controller_content);
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class MakeMiddlewareCommand extends Command
{
protected static $defaultName = 'make:middleware';
protected static $defaultDescription = 'Make middleware';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Middleware name');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument('name');
$output->writeln("Make middleware $name");
$name = str_replace('\\', '/', $name);
if (!$middleware_str = Util::guessPath(app_path(), 'middleware')) {
$middleware_str = Util::guessPath(app_path(), 'controller') === 'Controller' ? 'Middleware' : 'middleware';
}
$upper = $middleware_str === 'Middleware';
if (!($pos = strrpos($name, '/'))) {
$name = ucfirst($name);
$file = app_path() . "/$middleware_str/$name.php";
$namespace = $upper ? 'App\Middleware' : 'app\middleware';
} else {
if($real_name = Util::guessPath(app_path(), $name)) {
$name = $real_name;
}
if ($upper && !$real_name) {
$name = preg_replace_callback('/\/([a-z])/', function ($matches) {
return '/' . strtoupper($matches[1]);
}, ucfirst($name));
}
$path = "$middleware_str/" . substr($upper ? ucfirst($name) : $name, 0, $pos);
$name = ucfirst(substr($name, $pos + 1));
$file = app_path() . "/$path/$name.php";
$namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path);
}
$this->createMiddleware($name, $namespace, $file);
return self::SUCCESS;
}
/**
* @param $name
* @param $namespace
* @param $path
* @return void
*/
protected function createMiddleware($name, $namespace, $file)
{
$path = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$middleware_content = <<<EOF
<?php
namespace $namespace;
use Webman\MiddlewareInterface;
use Webman\Http\Response;
use Webman\Http\Request;
class $name implements MiddlewareInterface
{
public function process(Request \$request, callable \$next) : Response
{
return \$next(\$request);
}
}
EOF;
file_put_contents($file, $middleware_content);
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class MakeModelCommand extends Command
{
protected static $defaultName = 'make:model';
protected static $defaultDescription = 'Make model';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Model name');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument('name');
$name = Util::nameToClass($name);
$output->writeln("Make model $name");
if (!($pos = strrpos($name, '/'))) {
$name = ucfirst($name);
$model_str = Util::guessPath(app_path(), 'model') ?: 'model';
$file = app_path() . "/$model_str/$name.php";
$namespace = $model_str === 'Model' ? 'App\Model' : 'app\model';
} else {
$name_str = substr($name, 0, $pos);
if($real_name_str = Util::guessPath(app_path(), $name_str)) {
$name_str = $real_name_str;
} else if ($real_section_name = Util::guessPath(app_path(), strstr($name_str, '/', true))) {
$upper = strtolower($real_section_name[0]) !== $real_section_name[0];
} else if ($real_base_controller = Util::guessPath(app_path(), 'controller')) {
$upper = strtolower($real_base_controller[0]) !== $real_base_controller[0];
}
$upper = $upper ?? strtolower($name_str[0]) !== $name_str[0];
if ($upper && !$real_name_str) {
$name_str = preg_replace_callback('/\/([a-z])/', function ($matches) {
return '/' . strtoupper($matches[1]);
}, ucfirst($name_str));
}
$path = "$name_str/" . ($upper ? 'Model' : 'model');
$name = ucfirst(substr($name, $pos + 1));
$file = app_path() . "/$path/$name.php";
$namespace = str_replace('/', '\\', ($upper ? 'App/' : 'app/') . $path);
}
if (!config('database') && config('thinkorm')) {
$this->createTpModel($name, $namespace, $file);
} else {
$this->createModel($name, $namespace, $file);
}
return self::SUCCESS;
}
/**
* @param $class
* @param $namespace
* @param $file
* @return void
*/
protected function createModel($class, $namespace, $file)
{
$path = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$table = Util::classToName($class);
$table_val = 'null';
$pk = 'id';
$properties = '';
try {
$prefix = config('database.connections.mysql.prefix') ?? '';
$database = config('database.connections.mysql.database');
if (\support\Db::select("show tables like '{$prefix}{$table}s'")) {
$table = "{$prefix}{$table}s";
} else if (\support\Db::select("show tables like '{$prefix}{$table}'")) {
$table_val = "'$table'";
$table = "{$prefix}{$table}";
}
foreach (\support\Db::select("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database'") as $item) {
if ($item->COLUMN_KEY === 'PRI') {
$pk = $item->COLUMN_NAME;
$item->COLUMN_COMMENT .= "(主键)";
}
$type = $this->getType($item->DATA_TYPE);
$properties .= " * @property $type \${$item->COLUMN_NAME} {$item->COLUMN_COMMENT}\n";
}
} catch (\Throwable $e) {}
$properties = rtrim($properties) ?: ' *';
$model_content = <<<EOF
<?php
namespace $namespace;
use support\Model;
/**
$properties
*/
class $class extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected \$table = $table_val;
/**
* The primary key associated with the table.
*
* @var string
*/
protected \$primaryKey = '$pk';
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public \$timestamps = false;
}
EOF;
file_put_contents($file, $model_content);
}
/**
* @param $class
* @param $namespace
* @param $path
* @return void
*/
protected function createTpModel($class, $namespace, $file)
{
$path = pathinfo($file, PATHINFO_DIRNAME);
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$table = Util::classToName($class);
$table_val = 'null';
$pk = 'id';
$properties = '';
try {
$prefix = config('thinkorm.connections.mysql.prefix') ?? '';
$database = config('thinkorm.connections.mysql.database');
if (\think\facade\Db::query("show tables like '{$prefix}{$table}'")) {
$table = "{$prefix}{$table}";
$table_val = "'$table'";
} else if (\think\facade\Db::query("show tables like '{$prefix}{$table}s'")) {
$table = "{$prefix}{$table}s";
$table_val = "'$table'";
}
foreach (\think\facade\Db::query("select COLUMN_NAME,DATA_TYPE,COLUMN_KEY,COLUMN_COMMENT from INFORMATION_SCHEMA.COLUMNS where table_name = '$table' and table_schema = '$database'") as $item) {
if ($item['COLUMN_KEY'] === 'PRI') {
$pk = $item['COLUMN_NAME'];
$item['COLUMN_COMMENT'] .= "(主键)";
}
$type = $this->getType($item['DATA_TYPE']);
$properties .= " * @property $type \${$item['COLUMN_NAME']} {$item['COLUMN_COMMENT']}\n";
}
} catch (\Throwable $e) {}
$properties = rtrim($properties) ?: ' *';
$model_content = <<<EOF
<?php
namespace $namespace;
use think\Model;
/**
$properties
*/
class $class extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected \$table = $table_val;
/**
* The primary key associated with the table.
*
* @var string
*/
protected \$pk = '$pk';
}
EOF;
file_put_contents($file, $model_content);
}
/**
* @param string $type
* @return string
*/
protected function getType(string $type)
{
if (strpos($type, 'int') !== false) {
return 'integer';
}
switch ($type) {
case 'varchar':
case 'string':
case 'text':
case 'date':
case 'time':
case 'guid':
case 'datetimetz':
case 'datetime':
case 'decimal':
case 'enum':
return 'string';
case 'boolean':
return 'integer';
case 'float':
return 'float';
default:
return 'mixed';
}
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Phar;
use RuntimeException;
class PharPackCommand extends Command
{
protected static $defaultName = 'phar:pack';
protected static $defaultDescription = 'Can be easily packaged a project into phar files. Easy to distribute and use.';
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->checkEnv();
$phar_file_output_dir = config('plugin.webman.console.app.phar_file_output_dir');
if (empty($phar_file_output_dir)) {
throw new RuntimeException('Please set the phar file output directory.');
}
if (!file_exists($phar_file_output_dir) && !is_dir($phar_file_output_dir)) {
if (!mkdir($phar_file_output_dir,0777,true)) {
throw new RuntimeException("Failed to create phar file output directory. Please check the permission.");
}
}
$phar_filename = config('plugin.webman.console.app.phar_filename');
if (empty($phar_filename)) {
throw new RuntimeException('Please set the phar filename.');
}
$phar_file = rtrim($phar_file_output_dir,DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $phar_filename;
if (file_exists($phar_file)) {
unlink($phar_file);
}
$exclude_pattern = config('plugin.webman.console.app.exclude_pattern');
$phar = new Phar($phar_file,0,'webman');
$phar->startBuffering();
$signature_algorithm = config('plugin.webman.console.app.signature_algorithm');
if (!in_array($signature_algorithm,[Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512,Phar::OPENSSL])) {
throw new RuntimeException('The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.');
}
if ($signature_algorithm === Phar::OPENSSL) {
$private_key_file = config('plugin.webman.console.app.private_key_file');
if (!file_exists($private_key_file)) {
throw new RuntimeException("If the value of the signature algorithm is 'Phar::OPENSSL', you must set the private key file.");
}
$private = openssl_get_privatekey(file_get_contents($private_key_file));
$pkey = '';
openssl_pkey_export($private, $pkey);
$phar->setSignatureAlgorithm($signature_algorithm, $pkey);
} else {
$phar->setSignatureAlgorithm($signature_algorithm);
}
$phar->buildFromDirectory(BASE_PATH,$exclude_pattern);
$exclude_files = config('plugin.webman.console.app.exclude_files');
foreach ($exclude_files as $file) {
if($phar->offsetExists($file)){
$phar->delete($file);
}
}
$output->writeln('Files collect complete, begin add file to Phar.');
$phar->setStub("#!/usr/bin/env php
<?php
define('IN_PHAR', true);
Phar::mapPhar('webman');
require 'phar://webman/webman';
__HALT_COMPILER();
");
$output->writeln('Write requests to the Phar archive, save changes to disk.');
$phar->stopBuffering();
unset($phar);
return self::SUCCESS;
}
/**
* @throws RuntimeException
*/
private function checkEnv(): void
{
if (!class_exists(Phar::class, false)) {
throw new RuntimeException("The 'phar' extension is required for build phar package");
}
if (ini_get('phar.readonly')) {
throw new RuntimeException(
"The 'phar.readonly' is 'On', build phar must setting it 'Off' or exec with 'php -d phar.readonly=0 ./webman phar:pack'"
);
}
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Util;
class PluginCreateCommand extends Command
{
protected static $defaultName = 'plugin:create';
protected static $defaultDescription = 'Plugin create';
/**
* @return void
*/
protected function configure()
{
$this->addOption('name', 'name', InputOption::VALUE_REQUIRED, 'Plugin name, for example foo/my-admin');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = strtolower($input->getOption('name'));
$output->writeln("Create Plugin $name");
if (!strpos($name, '/')) {
$output->writeln('<error>Bad name, name must contain character \'/\' , for example foo/MyAdmin</error>');
return self::FAILURE;
}
$namespace = Util::nameToNamespace($name);
// Create dir config/plugin/$name
if (is_dir($plugin_config_path = config_path()."/plugin/$name")) {
$output->writeln("<error>Dir $plugin_config_path already exists</error>");
return self::FAILURE;
}
if (is_dir($plugin_path = base_path()."/vendor/$name")) {
$output->writeln("<error>Dir $plugin_path already exists</error>");
return self::FAILURE;
}
// Add psr-4
if ($err = $this->addAutoloadToComposerJson($name, $namespace)) {
$output->writeln("<error>$err</error>");
return self::FAILURE;
}
$this->createConfigFiles($plugin_config_path);
$this->createVendorFiles($name, $namespace, $plugin_path, $output);
return self::SUCCESS;
}
protected function addAutoloadToComposerJson($name, $namespace)
{
if (!is_file($composer_json_file = base_path()."/composer.json")) {
return "$composer_json_file not exists";
}
$composer_json = json_decode($composer_json_str = file_get_contents($composer_json_file), true);
if (!$composer_json) {
return "Bad $composer_json_file";
}
if(isset($composer_json['autoload']['psr-4'][$namespace."\\"])) {
return;
}
$namespace = str_replace("\\", "\\\\", $namespace);
$composer_json_str = str_replace('"psr-4": {', '"psr-4": {'."\n \"$namespace\\\\\" : \"vendor/$name/src\",", $composer_json_str);
file_put_contents($composer_json_file, $composer_json_str);
}
protected function createConfigFiles($plugin_config_path)
{
mkdir($plugin_config_path, 0777, true);
$app_str = <<<EOF
<?php
return [
'enable' => true,
];
EOF;
file_put_contents("$plugin_config_path/app.php", $app_str);
}
protected function createVendorFiles($name, $namespace, $plugin_path, $output)
{
mkdir("$plugin_path/src", 0777, true);
$this->createComposerJson($name, $namespace, $plugin_path);
if (is_callable('exec')) {
exec("composer dumpautoload");
} else {
$output->writeln("<info>Please run command 'composer dumpautoload'</info>");
}
}
/**
* @param $name
* @param $namespace
* @param $dest
* @return void
*/
protected function createComposerJson($name, $namespace, $dest)
{
$namespace = str_replace('\\', '\\\\', $namespace);
$composer_json_content = <<<EOT
{
"name": "$name",
"type": "library",
"license": "MIT",
"description": "Webman plugin $name",
"require": {
},
"autoload": {
"psr-4": {
"$namespace\\\\": "src"
}
}
}
EOT;
file_put_contents("$dest/composer.json", $composer_json_content);
}
/**
* @param $namespace
* @param $path_relations
* @param $dest_dir
* @return void
*/
protected function writeInstallFile($namespace, $path_relations, $dest_dir)
{
if (!is_dir($dest_dir)) {
mkdir($dest_dir, 0777, true);
}
$relations = [];
foreach($path_relations as $relation) {
$relations[$relation] = $relation;
}
$relations = var_export($relations, true);
$install_php_content = <<<EOT
<?php
namespace $namespace;
class Install
{
const WEBMAN_PLUGIN = true;
/**
* @var array
*/
protected static \$pathRelation = $relations;
/**
* Install
* @return void
*/
public static function install()
{
static::installByRelation();
}
/**
* Uninstall
* @return void
*/
public static function uninstall()
{
self::uninstallByRelation();
}
/**
* installByRelation
* @return void
*/
public static function installByRelation()
{
foreach (static::\$pathRelation as \$source => \$dest) {
if (\$pos = strrpos(\$dest, '/')) {
\$parent_dir = base_path().'/'.substr(\$dest, 0, \$pos);
if (!is_dir(\$parent_dir)) {
mkdir(\$parent_dir, 0777, true);
}
}
//symlink(__DIR__ . "/\$source", base_path()."/\$dest");
copy_dir(__DIR__ . "/\$source", base_path()."/\$dest");
}
}
/**
* uninstallByRelation
* @return void
*/
public static function uninstallByRelation()
{
foreach (static::\$pathRelation as \$source => \$dest) {
/*if (is_link(base_path()."/\$dest")) {
unlink(base_path()."/\$dest");
}*/
remove_dir(base_path()."/\$dest");
}
}
}
EOT;
file_put_contents("$dest_dir/Install.php", $install_php_content);
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
class PluginDisableCommand extends Command
{
protected static $defaultName = 'plugin:disable';
protected static $defaultDescription = 'Disable plugin by name';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getArgument('name');
$output->writeln("Disable plugin $name");
if (!strpos($name, '/')) {
$output->writeln('<error>Bad name, name must contain character \'/\' , for example foo/MyAdmin</error>');
return self::FAILURE;
}
$config_file = config_path() . "/plugin/$name/app.php";
if (!is_file($config_file)) {
return self::SUCCESS;
}
$config = include $config_file;
if (empty($config['enable'])) {
return self::SUCCESS;
}
$config_content = file_get_contents($config_file);
$config_content = preg_replace('/(\'enable\' *?=> *?)(true)/', '$1false', $config_content);
file_put_contents($config_file, $config_content);
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
class PluginEnableCommand extends Command
{
protected static $defaultName = 'plugin:enable';
protected static $defaultDescription = 'Enable plugin by name';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument('name');
$output->writeln("Enable plugin $name");
if (!strpos($name, '/')) {
$output->writeln('<error>Bad name, name must contain character \'/\' , for example foo/MyAdmin</error>');
return self::FAILURE;
}
$config_file = config_path() . "/plugin/$name/app.php";
if (!is_file($config_file)) {
$output->writeln("<error>$config_file not found</error>");
return self::FAILURE;
}
$config = include $config_file;
if (!isset($config['enable'])) {
$output->writeln("<error>Config key 'enable' not found</error>");
return self::FAILURE;
}
if ($config['enable']) {
return self::SUCCESS;
}
$config_content = file_get_contents($config_file);
$config_content = preg_replace('/(\'enable\' *?=> *?)(false)/', '$1true', $config_content);
file_put_contents($config_file, $config_content);
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Util;
class PluginExportCommand extends Command
{
protected static $defaultName = 'plugin:export';
protected static $defaultDescription = 'Plugin export';
/**
* @return void
*/
protected function configure()
{
$this->addOption('name', 'name', InputOption::VALUE_REQUIRED, 'Plugin name, for example foo/my-admin');
$this->addOption('source', 'source', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Directories to export');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('Export Plugin');
$name = strtolower($input->getOption('name'));
if (!strpos($name, '/')) {
$output->writeln('<error>Bad name, name must contain character \'/\' , for example foo/MyAdmin</error>');
return self::INVALID;
}
$namespace = Util::nameToNamespace($name);
$path_relations = $input->getOption('source');
if (!in_array("config/plugin/$name", $path_relations)) {
if (is_dir("config/plugin/$name")) {
$path_relations[] = "config/plugin/$name";
}
}
$original_dest = $dest = base_path()."/vendor/$name";
$dest .= '/src';
$this->writeInstallFile($namespace, $path_relations, $dest);
$output->writeln("<info>Create $dest/Install.php</info>");
foreach ($path_relations as $source) {
$base_path = pathinfo("$dest/$source", PATHINFO_DIRNAME);
if (!is_dir($base_path)) {
mkdir($base_path, 0777, true);
}
$output->writeln("<info>Copy $source to $dest/$source </info>");
copy_dir($source, "$dest/$source");
}
$output->writeln("<info>Saved $name to $original_dest</info>");
return self::SUCCESS;
}
/**
* @param $namespace
* @param $path_relations
* @param $dest_dir
* @return void
*/
protected function writeInstallFile($namespace, $path_relations, $dest_dir)
{
if (!is_dir($dest_dir)) {
mkdir($dest_dir, 0777, true);
}
$relations = [];
foreach($path_relations as $relation) {
$relations[$relation] = $relation;
}
$relations = var_export($relations, true);
$install_php_content = <<<EOT
<?php
namespace $namespace;
class Install
{
const WEBMAN_PLUGIN = true;
/**
* @var array
*/
protected static \$pathRelation = $relations;
/**
* Install
* @return void
*/
public static function install()
{
static::installByRelation();
}
/**
* Uninstall
* @return void
*/
public static function uninstall()
{
self::uninstallByRelation();
}
/**
* installByRelation
* @return void
*/
public static function installByRelation()
{
foreach (static::\$pathRelation as \$source => \$dest) {
if (\$pos = strrpos(\$dest, '/')) {
\$parent_dir = base_path().'/'.substr(\$dest, 0, \$pos);
if (!is_dir(\$parent_dir)) {
mkdir(\$parent_dir, 0777, true);
}
}
//symlink(__DIR__ . "/\$source", base_path()."/\$dest");
copy_dir(__DIR__ . "/\$source", base_path()."/\$dest");
echo "Create \$dest\r\n";
}
}
/**
* uninstallByRelation
* @return void
*/
public static function uninstallByRelation()
{
foreach (static::\$pathRelation as \$source => \$dest) {
\$path = base_path()."/\$dest";
if (!is_dir(\$path) && !is_file(\$path)) {
continue;
}
echo "Remove \$dest\r\n";
if (is_file(\$path) || is_link(\$path)) {
unlink(\$path);
continue;
}
remove_dir(\$path);
}
}
}
EOT;
file_put_contents("$dest_dir/Install.php", $install_php_content);
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class PluginInstallCommand extends Command
{
protected static $defaultName = 'plugin:install';
protected static $defaultDescription = 'Execute plugin installation script';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument('name');
$output->writeln("Execute installation for plugin $name");
$namespace = Util::nameToNamespace($name);
$install_function = "\\{$namespace}\\Install::install";
$plugin_const = "\\{$namespace}\\Install::WEBMAN_PLUGIN";
if (defined($plugin_const) && is_callable($install_function)) {
$install_function();
}
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Webman\Console\Util;
class PluginUninstallCommand extends Command
{
protected static $defaultName = 'plugin:uninstall';
protected static $defaultDescription = 'Execute plugin uninstall script';
/**
* @return void
*/
protected function configure()
{
$this->addArgument('name', InputArgument::REQUIRED, 'Plugin name, for example foo/my-admin');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$name = $input->getArgument('name');
$output->writeln("Execute uninstall for plugin $name");
if (!strpos($name, '/')) {
$output->writeln('<error>Bad name, name must contain character \'/\' , for example foo/MyAdmin</error>');
return self::FAILURE;
}
$namespace = Util::nameToNamespace($name);
$uninstall_function = "\\{$namespace}\\Install::uninstall";
$plugin_const = "\\{$namespace}\\Install::WEBMAN_PLUGIN";
if (defined($plugin_const) && is_callable($uninstall_function)) {
$uninstall_function();
}
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Application;
class ReStartCommand extends Command
{
protected static $defaultName = 'restart';
protected static $defaultDescription = 'Restart workers. Use mode -d to start in DAEMON mode. Use mode -g to stop gracefully.';
protected function configure() : void
{
$this
->addOption('daemon', 'd', InputOption::VALUE_NONE, 'DAEMON mode')
->addOption('graceful', 'g', InputOption::VALUE_NONE, 'graceful stop');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (\class_exists(\Support\App::class)) {
\Support\App::run();
return self::SUCCESS;
}
Application::run();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Application;
class ReloadCommand extends Command
{
protected static $defaultName = 'reload';
protected static $defaultDescription = 'Reload codes. Use mode -g to reload gracefully.';
protected function configure() : void
{
$this
->addOption('graceful', 'd', InputOption::VALUE_NONE, 'graceful reload');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (\class_exists(\Support\App::class)) {
\Support\App::run();
return self::SUCCESS;
}
Application::run();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\Table;
use Webman\Route;
class RouteListCommand extends Command
{
protected static $defaultName = 'route:list';
protected static $defaultDescription = 'Route list';
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$headers = ['uri', 'method', 'callback', 'middleware'];
$rows = [];
foreach (Route::getRoutes() as $route) {
foreach ($route->getMethods() as $method) {
$cb = $route->getCallback();
$cb = $cb instanceof \Closure ? 'Closure' : (is_array($cb) ? json_encode($cb) : var_export($cb, 1));
$rows[] = [$route->getPath(), $method, $cb, json_encode($route->getMiddleware() ?: null)];
}
}
$table = new Table($output);
$table->setHeaders($headers);
$table->setRows($rows);
$table->render();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Application;
class StartCommand extends Command
{
protected static $defaultName = 'start';
protected static $defaultDescription = 'Start worker in DEBUG mode. Use mode -d to start in DAEMON mode.';
protected function configure() : void
{
$this->addOption('daemon', 'd', InputOption::VALUE_NONE, 'DAEMON mode');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (\class_exists(\Support\App::class)) {
\Support\App::run();
return self::SUCCESS;
}
Application::run();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Application;
class StatusCommand extends Command
{
protected static $defaultName = 'status';
protected static $defaultDescription = 'Get worker status. Use mode -d to show live status.';
protected function configure() : void
{
$this->addOption('live', 'd', InputOption::VALUE_NONE, 'show live status');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (\class_exists(\Support\App::class)) {
\Support\App::run();
return self::SUCCESS;
}
Application::run();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Webman\Console\Application;
class StopCommand extends Command
{
protected static $defaultName = 'stop';
protected static $defaultDescription = 'Stop worker. Use mode -g to stop gracefully.';
protected function configure() : void
{
$this
->addOption('graceful', 'g',InputOption::VALUE_NONE, 'graceful stop');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if (\class_exists(\Support\App::class)) {
\Support\App::run();
return self::SUCCESS;
}
Application::run();
return self::SUCCESS;
}
}
<?php
namespace Webman\Console\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class VersionCommand extends Command
{
protected static $defaultName = 'version';
protected static $defaultDescription = 'Show webman version';
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$installed_file = base_path() . '/vendor/composer/installed.php';
if (is_file($installed_file)) {
$version_info = include $installed_file;
}
$webman_framework_version = $version_info['versions']['workerman/webman-framework']['pretty_version'] ?? '';
$output->writeln("Webman-framework $webman_framework_version");
return self::SUCCESS;
}
}
<?php
namespace Webman\Console;
class Install
{
const WEBMAN_PLUGIN = true;
/**
* @var array
*/
protected static $pathRelation = array (
'config/plugin/webman/console' => 'config/plugin/webman/console',
);
/**
* Install
* @return void
*/
public static function install()
{
copy(__DIR__ . "/webman", base_path()."/webman");
chmod(base_path()."/webman", 0755);
static::installByRelation();
}
/**
* Uninstall
* @return void
*/
public static function uninstall()
{
if (is_file(base_path()."/webman")) {
unlink(base_path() . "/webman");
}
self::uninstallByRelation();
}
/**
* installByRelation
* @return void
*/
public static function installByRelation()
{
foreach (static::$pathRelation as $source => $dest) {
if ($pos = strrpos($dest, '/')) {
$parent_dir = base_path().'/'.substr($dest, 0, $pos);
if (!is_dir($parent_dir)) {
mkdir($parent_dir, 0777, true);
}
}
//symlink(__DIR__ . "/$source", base_path()."/$dest");
copy_dir(__DIR__ . "/$source", base_path()."/$dest");
}
}
/**
* uninstallByRelation
* @return void
*/
public static function uninstallByRelation()
{
foreach (static::$pathRelation as $source => $dest) {
$path = base_path()."/$dest";
if (!is_dir($path) && !is_file($path)) {
continue;
}
/*if (is_link($path) {
unlink($path);
}*/
remove_dir($path);
}
}
}
<?php
namespace Webman\Console;
class Util
{
public static function nameToNamespace($name)
{
$namespace = ucfirst($name);
$namespace = preg_replace_callback(['/-([a-zA-Z])/', '/(\/[a-zA-Z])/'], function ($matches) {
return strtoupper($matches[1]);
}, $namespace);
return str_replace('/', '\\' ,ucfirst($namespace));
}
public static function classToName($class)
{
$class = lcfirst($class);
return preg_replace_callback(['/([A-Z])/'], function ($matches) {
return '_' . strtolower($matches[1]);
}, $class);
}
public static function nameToClass($class)
{
$class = preg_replace_callback(['/-([a-zA-Z])/', '/_([a-zA-Z])/'], function ($matches) {
return strtoupper($matches[1]);
}, $class);
if (!($pos = strrpos($class, '/'))) {
$class = ucfirst($class);
} else {
$path = substr($class, 0, $pos);
$class = ucfirst(substr($class, $pos + 1));
$class = "$path/$class";
}
return $class;
}
public static function guessPath($base_path, $name, $return_full_path = false)
{
if (!is_dir($base_path)) {
return false;
}
$names = explode('/', trim(strtolower($name), '/'));
$realname = [];
$path = $base_path;
foreach ($names as $name) {
$finded = false;
foreach (scandir($path) ?: [] as $tmp_name) {
if (strtolower($tmp_name) === $name && is_dir("$path/$tmp_name")) {
$path = "$path/$tmp_name";
$realname[] = $tmp_name;
$finded = true;
break;
}
}
if (!$finded) {
return false;
}
}
$realname = implode(DIRECTORY_SEPARATOR, $realname);
return $return_full_path ? realpath($base_path . DIRECTORY_SEPARATOR . $realname) : $realname;
}
}
<?php
return [
'enable' => true,
'phar_file_output_dir' => BASE_PATH . DIRECTORY_SEPARATOR . 'build',
'phar_filename' => 'webman.phar',
'signature_algorithm'=> Phar::SHA256, //set the signature algorithm for a phar and apply it. The signature algorithm must be one of Phar::MD5, Phar::SHA1, Phar::SHA256, Phar::SHA512, or Phar::OPENSSL.
'private_key_file' => '', // The file path for certificate or OpenSSL private key file.
//'exclude_pattern' => '#^(?!.*(config/plugin/webman/console/app.php|webman/console/src/Commands/(PharPackCommand.php|ReloadCommand.php)|LICENSE|composer.json|.github|.idea|doc|docs|.git|.setting|runtime|test|test_old|tests|Tests|vendor-bin|.md))(.*)$#',
'exclude_files' => [
'.env', 'LICENSE', 'composer.json', 'composer.lock','start.php'
]
];
#!/usr/bin/env php
<?php
use Webman\Config;
use Webman\Console\Command;
use Webman\Console\Util;
require_once __DIR__ . '/vendor/autoload.php';
if (!in_array($argv[1] ?? '', ['start', 'restart', 'stop', 'status', 'reload', 'connections'])) {
require_once __DIR__ . '/support/bootstrap.php';
} else {
if (class_exists('Support\App')) {
Support\App::loadAllConfig(['route']);
} else {
Config::reload(config_path(), ['route', 'container']);
}
}
$cli = new Command();
$cli->setName('webman cli');
$cli->installInternalCommands();
if (is_dir($command_path = Util::guessPath(app_path(), '/command', true))) {
$cli->installCommands($command_path);
}
foreach (config('plugin', []) as $firm => $projects) {
if (isset($projects['app'])) {
if ($command_str = Util::guessPath(base_path() . "/plugin/$firm", 'command')) {
$command_path = base_path() . "/plugin/$firm/$command_str";
$cli->installCommands($command_path, "plugin\\$firm\\$command_str");
}
}
foreach ($projects as $name => $project) {
if (!is_array($project)) {
continue;
}
foreach ($project['command'] ?? [] as $command) {
$cli->add(new $command);
}
}
}
$cli->run();
......@@ -11,6 +11,7 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Webman;
use Workerman\Worker;
......
......@@ -33,83 +33,169 @@ class Config
protected static $_loaded = false;
/**
* @param $config_path
* @param string $config_path
* @param array $exclude_file
* @param string|null $key
* @return void
*/
public static function load($config_path, $exclude_file = [])
public static function load(string $config_path, array $exclude_file = [], string $key = null)
{
static::$_configPath = $config_path;
if (!$config_path) {
return;
}
$dir_iterator = new \RecursiveDirectoryIterator($config_path, \FilesystemIterator::FOLLOW_SYMLINKS);
$iterator = new \RecursiveIteratorIterator($dir_iterator);
foreach ($iterator as $file) {
/** var SplFileInfo $file */
if (is_dir($file) || $file->getExtension() != 'php' || \in_array($file->getBaseName('.php'), $exclude_file)) {
continue;
static::$_loaded = false;
$config = static::loadFromDir($config_path, $exclude_file);
if (!$config) {
static::$_loaded = true;
return;
}
if ($key !== null) {
foreach (\array_reverse(\explode('.', $key)) as $k) {
$config = [$k => $config];
}
$app_config_file = $file->getPath() . '/app.php';
if (!is_file($app_config_file)) {
continue;
}
static::$_config = \array_replace_recursive(static::$_config, $config);
static::formatConfig();
static::$_loaded = true;
}
/**
* This deprecated method will certainly be removed in the future
*
* @deprecated
* @param string $config_path
* @param array $exclude_file
* @return void
*/
public static function reload(string $config_path, array $exclude_file = [])
{
static::load($config_path, $exclude_file);
}
/**
* @return void
*/
protected static function formatConfig()
{
$config = static::$_config;
// Merge log config
foreach ($config['plugin'] ?? [] as $firm => $projects) {
if (isset($projects['app'])) {
foreach ($projects['log'] ?? [] as $key => $item) {
$config['log']["plugin.$firm.$key"] = $item;
}
}
$relative_path = str_replace($config_path . DIRECTORY_SEPARATOR, '', substr($file, 0, -4));
$explode = array_reverse(explode(DIRECTORY_SEPARATOR, $relative_path));
if (count($explode) >= 2) {
$app_config = include $app_config_file;
if (empty($app_config['enable'])) {
foreach ($projects as $name => $project) {
if (!\is_array($project)) {
continue;
}
foreach ($project['log'] ?? [] as $key => $item) {
$config['log']["plugin.$firm.$name.$key"] = $item;
}
}
$config = include $file;
foreach ($explode as $section) {
$tmp = [];
$tmp[$section] = $config;
$config = $tmp;
}
static::$_config = array_replace_recursive(static::$_config, $config);
}
// Merge database config
foreach (static::$_config['plugin'] ?? [] as $firm => $projects) {
foreach ($config['plugin'] ?? [] as $firm => $projects) {
if (isset($projects['app'])) {
foreach ($projects['database']['connections'] ?? [] as $key => $connection) {
$config['database']['connections']["plugin.$firm.$key"] = $connection;
}
}
foreach ($projects as $name => $project) {
if (!\is_array($project)) {
continue;
}
foreach ($project['database']['connections'] ?? [] as $key => $connection) {
static::$_config['database']['connections']["plugin.$firm.$name.$key"] = $connection;
$config['database']['connections']["plugin.$firm.$name.$key"] = $connection;
}
}
}
if (!empty(static::$_config['database']['connections'])) {
static::$_config['database']['default'] = static::$_config['database']['default'] ?? key(static::$_config['database']['connections']);
if (!empty($config['database']['connections'])) {
$config['database']['default'] = $config['database']['default'] ?? key($config['database']['connections']);
}
// Merge thinkorm config
foreach (static::$_config['plugin'] ?? [] as $firm => $projects) {
foreach ($config['plugin'] ?? [] as $firm => $projects) {
if (isset($projects['app'])) {
foreach ($projects['thinkorm']['connections'] ?? [] as $key => $connection) {
$config['thinkorm']['connections']["plugin.$firm.$key"] = $connection;
}
}
foreach ($projects as $name => $project) {
if (!\is_array($project)) {
continue;
}
foreach ($project['thinkorm']['connections'] ?? [] as $key => $connection) {
static::$_config['thinkorm']['connections']["plugin.$firm.$name.$key"] = $connection;
$config['thinkorm']['connections']["plugin.$firm.$name.$key"] = $connection;
}
}
}
if (!empty(static::$_config['thinkorm']['connections'])) {
static::$_config['thinkorm']['default'] = static::$_config['thinkorm']['default'] ?? key(static::$_config['thinkorm']['connections']);
if (!empty($config['thinkorm']['connections'])) {
$config['thinkorm']['default'] = $config['thinkorm']['default'] ?? \key($config['thinkorm']['connections']);
}
// Merge redis config
foreach (static::$_config['plugin'] ?? [] as $firm => $projects) {
foreach ($config['plugin'] ?? [] as $firm => $projects) {
if (isset($projects['app'])) {
foreach ($projects['redis'] ?? [] as $key => $connection) {
$config['redis']["plugin.$firm.$key"] = $connection;
}
}
foreach ($projects as $name => $project) {
if (!\is_array($project)) {
continue;
}
foreach ($project['redis'] ?? [] as $key => $connection) {
static::$_config['redis']["plugin.$firm.$name.$key"] = $connection;
$config['redis']["plugin.$firm.$name.$key"] = $connection;
}
}
}
static::$_config = $config;
}
static::$_loaded = true;
/**
* @param string $config_path
* @param array $exclude_file
* @return array
*/
public static function loadFromDir(string $config_path, array $exclude_file = [])
{
$all_config = [];
$dir_iterator = new \RecursiveDirectoryIterator($config_path, \FilesystemIterator::FOLLOW_SYMLINKS);
$iterator = new \RecursiveIteratorIterator($dir_iterator);
foreach ($iterator as $file) {
/** var SplFileInfo $file */
if (\is_dir($file) || $file->getExtension() != 'php' || \in_array($file->getBaseName('.php'), $exclude_file)) {
continue;
}
$app_config_file = $file->getPath() . '/app.php';
if (!\is_file($app_config_file)) {
continue;
}
$relative_path = \str_replace($config_path . DIRECTORY_SEPARATOR, '', substr($file, 0, -4));
$explode = \array_reverse(\explode(DIRECTORY_SEPARATOR, $relative_path));
if (\count($explode) >= 2) {
$app_config = include $app_config_file;
if (empty($app_config['enable'])) {
continue;
}
}
$config = include $file;
foreach ($explode as $section) {
$tmp = [];
$tmp[$section] = $config;
$config = $tmp;
}
$all_config = \array_replace_recursive($all_config, $config);
}
return $all_config;
}
/**
* @param null $key
* @param null $default
* @return array|mixed|null
* @param string|null $key
* @param mixed $default
* @return array|mixed|void|null
*/
public static function get($key = null, $default = null)
public static function get(string $key = null, $default = null)
{
if ($key === null) {
return static::$_config;
......@@ -134,11 +220,11 @@ class Config
}
/**
* @param $key
* @param $default
* @return array|mixed|void|null
* @param string $key
* @param mixed $default
* @return array|mixed|null
*/
protected static function read($key, $default = null)
protected static function read(string $key, $default = null)
{
$path = static::$_configPath;
if ($path === '') {
......@@ -147,11 +233,11 @@ class Config
$keys = $key_array = \explode('.', $key);
foreach ($key_array as $index => $section) {
unset($keys[$index]);
if (is_file($file = "$path/$section.php")) {
if (\is_file($file = "$path/$section.php")) {
$config = include $file;
return static::find($keys, $config, $default);
}
if (!is_dir($path = "$path/$section")) {
if (!\is_dir($path = "$path/$section")) {
return $default;
}
}
......@@ -159,14 +245,14 @@ class Config
}
/**
* @param $key_array
* @param $stack
* @param $default
* @param array $key_array
* @param mixed $stack
* @param mixed $default
* @return array|mixed
*/
protected static function find($key_array, $stack, $default)
protected static function find(array $key_array, $stack, $default)
{
if (!is_array($stack)) {
if (!\is_array($stack)) {
return $default;
}
$value = $stack;
......@@ -179,15 +265,4 @@ class Config
return $value;
}
/**
* @param $config_path
* @param array $exclude_file
*/
public static function reload($config_path, $exclude_file = [])
{
static::$_config = [];
static::load($config_path, $exclude_file);
}
}
<?php
namespace Webman;
use Psr\Container\ContainerInterface;
......@@ -21,10 +22,10 @@ class Container implements ContainerInterface
* @return mixed
* @throws NotFoundException
*/
public function get($name)
public function get(string $name)
{
if (!isset($this->_instances[$name])) {
if (!class_exists($name)) {
if (!\class_exists($name)) {
throw new NotFoundException("Class '$name' not found");
}
$this->_instances[$name] = new $name();
......@@ -36,20 +37,20 @@ class Container implements ContainerInterface
* @param string $name
* @return bool
*/
public function has($name): bool
public function has(string $name): bool
{
return \array_key_exists($name, $this->_instances);
}
/**
* @param $name
* @param string $name
* @param array $constructor
* @return mixed
* @throws NotFoundException
*/
public function make($name, array $constructor = [])
public function make(string $name, array $constructor = [])
{
if (!class_exists($name)) {
if (!\class_exists($name)) {
throw new NotFoundException("Class '$name' not found");
}
return new $name(... array_values($constructor));
......
......@@ -11,16 +11,17 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Webman\Exception;
use Throwable;
use Psr\Log\LoggerInterface;
use Throwable;
use Webman\Http\Request;
use Webman\Http\Response;
/**
* Class Handler
* @package support\exception
* @package Support\Exception
*/
class ExceptionHandler implements ExceptionHandlerInterface
{
......@@ -37,9 +38,7 @@ class ExceptionHandler implements ExceptionHandlerInterface
/**
* @var array
*/
public $dontReport = [
];
public $dontReport = [];
/**
* ExceptionHandler constructor.
......@@ -61,8 +60,11 @@ class ExceptionHandler implements ExceptionHandlerInterface
if ($this->shouldntReport($exception)) {
return;
}
$this->_logger->error($exception->getMessage(), ['exception' => (string)$exception]);
$logs = '';
if ($request = \request()) {
$logs = $request->getRealIp() . ' ' . $request->method() . ' ' . \trim($request->fullUrl(), '/');
}
$this->_logger->error($logs . PHP_EOL . $exception);
}
/**
......@@ -70,16 +72,16 @@ class ExceptionHandler implements ExceptionHandlerInterface
* @param Throwable $exception
* @return Response
*/
public function render(Request $request, Throwable $exception) : Response
public function render(Request $request, Throwable $exception): Response
{
$code = $exception->getCode();
if ($request->expectsJson()) {
$json = ['code' => $code ? $code : 500, 'msg' => $exception->getMessage()];
$json = ['code' => $code ? $code : 500, 'msg' => $this->_debug ? $exception->getMessage() : 'Server internal error'];
$this->_debug && $json['traces'] = (string)$exception;
return new Response(200, ['Content-Type' => 'application/json'],
json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
\json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
$error = $this->_debug ? nl2br((string)$exception) : 'Server internal error';
$error = $this->_debug ? \nl2br((string)$exception) : 'Server internal error';
return new Response(500, [], $error);
}
......@@ -87,7 +89,8 @@ class ExceptionHandler implements ExceptionHandlerInterface
* @param Throwable $e
* @return bool
*/
protected function shouldntReport(Throwable $e) {
protected function shouldntReport(Throwable $e)
{
foreach ($this->dontReport as $type) {
if ($e instanceof $type) {
return true;
......
......@@ -11,6 +11,7 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Webman\Exception;
use Throwable;
......@@ -30,5 +31,5 @@ interface ExceptionHandlerInterface
* @param Throwable $e
* @return Response
*/
public function render(Request $request, Throwable $e) : Response;
public function render(Request $request, Throwable $e): Response;
}
\ No newline at end of file
......@@ -11,12 +11,15 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Webman\Exception;
use RuntimeException;
/**
* Class FileException
* @package Webman\Exception
*/
class FileException extends \RuntimeException
class FileException extends RuntimeException
{
}
\ No newline at end of file
......@@ -13,15 +13,13 @@
*/
namespace Webman;
use FastRoute\Dispatcher\GroupCountBased;
use FastRoute\RouteCollector;
use Workerman\Protocols\Http\Session\FileSessionHandler as SessionHandler;
/**
* Class FileSessionHandler
* This deprecated class will certainly be removed in the future.
* Please use Webman\Session\FileSessionHandler
* @deprecated
* @package Webman
*/
class FileSessionHandler extends SessionHandler
class FileSessionHandler extends Session\FileSessionHandler
{
}
......@@ -11,6 +11,7 @@
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace Webman;
use Webman\Http\Request;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册