fix:更新已知bug,优化代码

This commit is contained in:
Ying
2022-11-28 19:11:12 +08:00
parent f6aee95cfc
commit 9445b206a2
1378 changed files with 53759 additions and 20789 deletions

View File

@@ -1,4 +1,5 @@
<?php
/**
* This file is part of webman.
*
@@ -18,6 +19,9 @@ use Closure;
use FastRoute\Dispatcher;
use Monolog\Logger;
use Psr\Container\ContainerInterface;
use ReflectionFunction;
use ReflectionFunctionAbstract;
use ReflectionMethod;
use Throwable;
use Webman\Exception\ExceptionHandler;
use Webman\Exception\ExceptionHandlerInterface;
@@ -118,7 +122,8 @@ class App
return static::send($connection, $callback($request), $request);
}
if (static::unsafeUri($connection, $path, $request) ||
if (
static::unsafeUri($connection, $path, $request) ||
static::findFile($connection, $path, $key, $request) ||
static::findRoute($connection, $path, $key, $request)
) {
@@ -126,13 +131,13 @@ class App
}
$controller_and_action = static::parseControllerAction($path);
if (!$controller_and_action || Route::hasDisableDefaultRoute()) {
$plugin = $controller_and_action['plugin'] ?? '';
if (!$controller_and_action || Route::hasDisableDefaultRoute($plugin)) {
$callback = static::getFallback();
$request->app = $request->controller = $request->action = '';
static::send($connection, $callback($request), $request);
return null;
}
$plugin = $controller_and_action['plugin'];
$app = $controller_and_action['app'];
$controller = $controller_and_action['controller'];
$action = $controller_and_action['action'];
@@ -177,12 +182,14 @@ class App
*/
protected static function unsafeUri(TcpConnection $connection, string $path, $request)
{
if (\strpos($path, '..') !== false ||
if (
!$path ||
\strpos($path, '..') !== false ||
\strpos($path, "\\") !== false ||
\strpos($path, "\0") !== false ||
\strpos($path, '//') !== false || !$path) {
\strpos($path, "\0") !== false
) {
$callback = static::getFallback();
$request->app = $request->controller = $request->action = '';
$request->plugin = $request->app = $request->controller = $request->action = '';
static::send($connection, $callback($request), $request);
return true;
}
@@ -196,7 +203,12 @@ class App
{
// when route, controller and action not found, try to use Route::fallback
return Route::getFallback() ?: function () {
return new Response(404, [], \file_get_contents(static::$_publicPath . '/404.html'));
try {
$notFoundContent = \file_get_contents(static::$_publicPath . '/404.html');
} catch (Throwable $e) {
$notFoundContent = '404 Not Found';
}
return new Response(404, [], $notFoundContent);
};
}
@@ -233,7 +245,7 @@ class App
/**
* @param $app
* @param $call
* @param null $args
* @param array|null $args
* @param bool $with_global_middleware
* @param RouteObject $route
* @return callable
@@ -253,18 +265,34 @@ class App
foreach ($middlewares as $key => $item) {
$middlewares[$key][0] = static::container($plugin)->get($item[0]);
}
$controller_reuse = static::config($plugin, 'app.controller_reuse', true);
$need_inject = static::isNeedInject($call, $args);
if (\is_array($call) && \is_string($call[0])) {
$controller_reuse = static::config($plugin, 'app.controller_reuse', true);
if (!$controller_reuse) {
$call = function ($request, ...$args) use ($call, $plugin) {
$call[0] = static::container($plugin)->make($call[0]);
return $call($request, ...$args);
};
if ($need_inject) {
$call = function ($request, ...$args) use ($call, $plugin) {
$call[0] = static::container($plugin)->make($call[0]);
$reflector = static::getReflector($call);
$args = static::resolveMethodDependencies($plugin, $request, $args, $reflector);
return $call(...$args);
};
$need_inject = false;
} else {
$call = function ($request, ...$args) use ($call, $plugin) {
$call[0] = static::container($plugin)->make($call[0]);
return $call($request, ...$args);
};
}
} else {
$call[0] = static::container($plugin)->get($call[0]);
}
}
if ($need_inject) {
$call = static::resolveInject($plugin, $call);
}
if ($middlewares) {
$callback = \array_reduce($middlewares, function ($carry, $pipe) {
return function ($request) use ($carry, $pipe) {
@@ -300,6 +328,129 @@ class App
return $callback;
}
/**
* @param string $plugin
* @param array|Closure $call
* @param null|array $args
* @return Closure
* @see Dependency injection through reflection information
*/
protected static function resolveInject(string $plugin, $call)
{
return function (Request $request, ...$args) use ($plugin, $call) {
$reflector = static::getReflector($call);
$args = static::resolveMethodDependencies($plugin, $request, $args, $reflector);
return $call(...$args);
};
}
/**
* Check whether inject is required
*
* @param $call
* @param $args
* @return bool
* @throws \ReflectionException
*/
protected static function isNeedInject($call, $args)
{
$args = $args ?: [];
$reflector = static::getReflector($call);
$reflection_parameters = $reflector->getParameters();
if (!$reflection_parameters) {
return false;
}
$first_parameter = \current($reflection_parameters);
unset($reflection_parameters[\key($reflection_parameters)]);
$adapters_list = ['int', 'string', 'bool', 'array', 'object', 'float', 'mixed', 'resource'];
foreach ($reflection_parameters as $parameter) {
if ($parameter->hasType() && !\in_array($parameter->getType()->getName(), $adapters_list)) {
return true;
}
}
if (!$first_parameter->hasType()) {
if (\count($args) <= count($reflection_parameters)) {
return false;
}
return true;
} elseif (!\is_a(static::$_request, $first_parameter->getType()->getName())) {
return true;
}
return false;
}
/**
* Get reflector.
*
* @param $call
* @return void
* @throws \ReflectionException
*/
protected static function getReflector($call)
{
if ($call instanceof Closure) {
return new ReflectionFunction($call);
}
return new ReflectionMethod($call[0], $call[1]);
}
/**
* Return dependent parameters
*
* @param string $plugin
* @param Request $request
* @param array $args
* @param ReflectionFunctionAbstract $reflector
* @return array
*/
protected static function resolveMethodDependencies(string $plugin, Request $request, array $args, ReflectionFunctionAbstract $reflector)
{
// Specification parameter information
$args = \array_values($args);
$parameters = [];
// An array of reflection classes for loop parameters, with each $parameter representing a reflection object of parameters
foreach ($reflector->getParameters() as $parameter) {
// Parameter quota consumption
if ($parameter->hasType()) {
$name = $parameter->getType()->getName();
switch ($name) {
case 'int':
case 'string':
case 'bool':
case 'array':
case 'object':
case 'float':
case 'mixed':
case 'resource':
goto _else;
default:
if (\is_a(static::$_request, $name)) {
//Inject Request
$parameters[] = $request;
} else {
$parameters[] = static::container($plugin)->make($name);
}
break;
}
} else {
_else:
// The variable parameter
if (null !== \key($args)) {
$parameters[] = \current($args);
} else {
// Indicates whether the current parameter has a default value. If yes, return true
$parameters[] = $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null;
}
// Quota of consumption variables
\next($args);
}
}
// Returns the result of parameters replacement
return $parameters;
}
/**
* @param string $plugin
* @return ContainerInterface
@@ -310,7 +461,7 @@ class App
}
/**
* @return Request
* @return Request|\support\Request
*/
public static function request()
{
@@ -454,6 +605,7 @@ class App
*/
protected static function parseControllerAction(string $path)
{
$path = \str_replace('-', '', $path);
$path_explode = \explode('/', trim($path, '/'));
$is_plugin = isset($path_explode[1]) && $path_explode[0] === 'app';
$config_prefix = $is_plugin ? "plugin.{$path_explode[1]}." : '';

View File

@@ -73,6 +73,14 @@ class Config
static::load($config_path, $exclude_file);
}
/**
* @return void
*/
public static function clear()
{
static::$_config = [];
}
/**
* @return void
*/

View File

@@ -16,6 +16,10 @@ class Container implements ContainerInterface
* @var array
*/
protected $_instances = [];
/**
* @var array
*/
protected $_definitions = [];
/**
* @param string $name
@@ -25,10 +29,14 @@ class Container implements ContainerInterface
public function get(string $name)
{
if (!isset($this->_instances[$name])) {
if (!\class_exists($name)) {
throw new NotFoundException("Class '$name' not found");
if (isset($this->_definitions[$name])) {
$this->_instances[$name] = call_user_func($this->_definitions[$name], $this);
} else {
if (!\class_exists($name)) {
throw new NotFoundException("Class '$name' not found");
}
$this->_instances[$name] = new $name();
}
$this->_instances[$name] = new $name();
}
return $this->_instances[$name];
}
@@ -39,7 +47,8 @@ class Container implements ContainerInterface
*/
public function has(string $name): bool
{
return \array_key_exists($name, $this->_instances);
return \array_key_exists($name, $this->_instances)
|| array_key_exists($name, $this->_definitions);
}
/**
@@ -56,4 +65,14 @@ class Container implements ContainerInterface
return new $name(... array_values($constructor));
}
/**
* @param array $definitions
* @return $this
*/
public function addDefinitions(array $definitions)
{
$this->_definitions = array_merge($this->_definitions, $definitions);
return $this;
}
}

View File

@@ -21,7 +21,7 @@ use Webman\Http\Response;
/**
* Class Handler
* @package Support\Exception
* @package support\exception
*/
class ExceptionHandler implements ExceptionHandlerInterface
{

View File

@@ -64,7 +64,7 @@ class UploadFile extends File
/**
* @return string
*/
public function getUploadMineType()
public function getUploadMimeType()
{
return $this->_uploadMimeType;
}
@@ -93,4 +93,12 @@ class UploadFile extends File
return $this->_uploadErrorCode === UPLOAD_ERR_OK;
}
}
/**
* @deprecated
* @return string
*/
public function getUploadMineType()
{
return $this->_uploadMimeType;
}
}

View File

@@ -47,8 +47,12 @@ class Install
mkdir($parent_dir, 0777, true);
}
}
copy_dir(__DIR__ . "/$source", base_path() . "/$dest", true);
$source_file = __DIR__ . "/$source";
copy_dir($source_file, base_path() . "/$dest", true);
echo "Create $dest\r\n";
if (is_file($source_file)) {
@unlink($source_file);
}
}
}

View File

@@ -358,7 +358,7 @@ class Route
require_once $route_config_file;
}
if (!is_dir($plugin_config_path = $config_path . '/plugin')) {
return;
continue;
}
$dir_iterator = new \RecursiveDirectoryIterator($plugin_config_path, \FilesystemIterator::FOLLOW_SYMLINKS);
$iterator = new \RecursiveIteratorIterator($dir_iterator);

View File

@@ -1,4 +0,0 @@
#!/usr/bin/env php
<?php
require_once __DIR__ . '/vendor/autoload.php';
Support\App::run();

View File

@@ -19,11 +19,11 @@ class App
ini_set('display_errors', 'on');
error_reporting(E_ALL);
if (class_exists(Dotenv::class) && file_exists(base_path() . '/.env')) {
if (class_exists(Dotenv::class) && file_exists(run_path('.env'))) {
if (method_exists(Dotenv::class, 'createUnsafeImmutable')) {
Dotenv::createUnsafeImmutable(base_path())->load();
Dotenv::createUnsafeImmutable(run_path())->load();
} else {
Dotenv::createMutable(base_path())->load();
Dotenv::createMutable(run_path())->load();
}
}
@@ -97,7 +97,7 @@ class App
require_once \base_path() . '/support/bootstrap.php';
$app = new \Webman\App(config('app.request_class', Request::class), Log::channel('default'), app_path(), public_path());
$worker->onMessage = [$app, 'onMessage'];
[$app, 'onWorkerStart']($worker);
\call_user_func([$app, 'onWorkerStart'], $worker);
};
}

View File

@@ -7,7 +7,7 @@ use Symfony\Component\Cache\Psr16Cache;
/**
* Class Cache
* @package Support\Bootstrap
* @package support\bootstrap
*
* Strings methods
* @method static mixed get($key, $default = null)

View File

@@ -19,7 +19,7 @@ use Webman\Config;
/**
* Class Container
* @package Support
* @package support
* @method static mixed get($name)
* @method static mixed make($name, array $parameters)
* @method static bool has($name)

View File

@@ -18,7 +18,7 @@ use Illuminate\Database\Capsule\Manager;
/**
* Class Db
* @package Support
* @package support
* @method static array select(string $query, $bindings = [], $useReadPdo = true)
* @method static int insert(string $query, $bindings = [])
* @method static int update(string $query, $bindings = [])

View File

@@ -21,7 +21,7 @@ use Monolog\Logger;
/**
* Class Log
* @package Support
* @package support
*
* @method static void log($level, $message, array $context = [])
* @method static void debug($message, array $context = [])

View File

@@ -23,7 +23,7 @@ use Workerman\Worker;
/**
* Class Redis
* @package Support
* @package support
*
* Strings methods
* @method static int append($key, $value)

View File

@@ -16,7 +16,7 @@ namespace support;
/**
* Class Request
* @package Support
* @package support
*/
class Request extends \Webman\Http\Request
{

View File

@@ -16,7 +16,7 @@ namespace support;
/**
* Class Response
* @package Support
* @package support
*/
class Response extends \Webman\Http\Response
{

View File

@@ -19,7 +19,7 @@ use Webman\Exception\NotFoundException;
/**
* Class Translation
* @package Support
* @package support
* @method static string trans(?string $id, array $parameters = [], string $domain = null, string $locale = null)
* @method static void setLocale(string $locale)
* @method static string getLocale()

View File

@@ -1,132 +0,0 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use Dotenv\Dotenv;
use support\Log;
use Webman\Bootstrap;
use Webman\Config;
use Webman\Route;
use Webman\Middleware;
use Webman\Util;
$worker = $worker ?? null;
if ($timezone = config('app.default_timezone')) {
date_default_timezone_set($timezone);
}
set_error_handler(function ($level, $message, $file = '', $line = 0) {
if (error_reporting() & $level) {
throw new ErrorException($message, 0, $level, $file, $line);
}
});
if ($worker) {
register_shutdown_function(function ($start_time) {
if (time() - $start_time <= 1) {
sleep(1);
}
}, time());
}
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();
}
}
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;
}
}
Middleware::load(config('middleware', []), '');
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
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', [])], '');
foreach (config('bootstrap', []) as $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) {
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);

View File

@@ -21,7 +21,7 @@ use Workerman\Worker;
/**
* Class Session
* @package Support
* @package support
*/
class Session implements Bootstrap
{

View File

@@ -15,12 +15,23 @@
namespace support\exception;
use Exception;
use Webman\Http\Response;
use Webman\Http\Request;
/**
* Class BusinessException
* @package Support\Exception
* @package support\exception
*/
class BusinessException extends Exception
{
}
public function render(Request $request): ?Response
{
if ($request->expectsJson()) {
$code = $this->getCode();
$json = ['code' => $code ? $code : 500, 'msg' => $this->getMessage()];
return new Response(200, ['Content-Type' => 'application/json'],
\json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
return new Response(200, [], $this->getMessage());
}
}

View File

@@ -21,7 +21,7 @@ use Webman\Http\Response;
/**
* Class Handler
* @package Support\Exception
* @package support\exception
*/
class Handler extends ExceptionHandler
{
@@ -36,6 +36,11 @@ class Handler extends ExceptionHandler
public function render(Request $request, Throwable $exception): Response
{
if(($exception instanceof BusinessException) && ($response = $exception->render($request)))
{
return $response;
}
return parent::render($request, $exception);
}

View File

@@ -1,482 +0,0 @@
<?php
/**
* This file is part of webman.
*
* Licensed under The MIT License
* For full copyright and license information, please see the MIT-LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @author walkor<walkor@workerman.net>
* @copyright walkor<walkor@workerman.net>
* @link http://www.workerman.net/
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
use support\Request;
use support\Response;
use support\Translation;
use support\Container;
use support\view\Raw;
use support\view\Blade;
use support\view\ThinkPHP;
use support\view\Twig;
use Workerman\Worker;
use Webman\App;
use Webman\Config;
use Webman\Route;
// Phar support.
if (\is_phar()) {
\define('BASE_PATH', dirname(__DIR__));
} else {
\define('BASE_PATH', realpath(__DIR__ . '/../'));
}
\define('WEBMAN_VERSION', '1.4');
/**
* @param $return_phar
* @return false|string
*/
function base_path(bool $return_phar = true)
{
static $real_path = '';
if (!$real_path) {
$real_path = \is_phar() ? \dirname(Phar::running(false)) : BASE_PATH;
}
return $return_phar ? BASE_PATH : $real_path;
}
/**
* @return string
*/
function app_path()
{
return BASE_PATH . DIRECTORY_SEPARATOR . 'app';
}
/**
* @return string
*/
function public_path()
{
static $path = '';
if (!$path) {
$path = \config('app.public_path', BASE_PATH . DIRECTORY_SEPARATOR . 'public');
}
return $path;
}
/**
* @return string
*/
function config_path()
{
return BASE_PATH . DIRECTORY_SEPARATOR . 'config';
}
/**
* Phar support.
* Compatible with the 'realpath' function in the phar file.
*
* @return string
*/
function runtime_path()
{
static $path = '';
if (!$path) {
$path = \config('app.runtime_path', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime');
}
return $path;
}
/**
* @param int $status
* @param array $headers
* @param string $body
* @return Response
*/
function response($body = '', $status = 200, $headers = [])
{
return new Response($status, $headers, $body);
}
/**
* @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));
}
/**
* @param $xml
* @return Response
*/
function xml($xml)
{
if ($xml instanceof SimpleXMLElement) {
$xml = $xml->asXML();
}
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
}
/**
* @param $data
* @param string $callback_name
* @return Response
*/
function jsonp($data, $callback_name = 'callback')
{
if (!\is_scalar($data) && null !== $data) {
$data = \json_encode($data);
}
return new Response(200, [], "$callback_name($data)");
}
/**
* @param string $location
* @param int $status
* @param array $headers
* @return Response
*/
function redirect(string $location, int $status = 302, array $headers = [])
{
$response = new Response($status, ['Location' => $location]);
if (!empty($headers)) {
$response->withHeaders($headers);
}
return $response;
}
/**
* @param $template
* @param array $vars
* @param null $app
* @return Response
*/
function view(string $template, array $vars = [], string $app = null)
{
$request = \request();
$plugin = $request->plugin ?? '';
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
return new Response(200, [], $handler::render($template, $vars, $app));
}
/**
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
* @throws Throwable
*/
function raw_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], Raw::render($template, $vars, $app));
}
/**
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
function blade_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], Blade::render($template, $vars, $app));
}
/**
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
function think_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
}
/**
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
function twig_view(string $template, array $vars = [], string $app = null)
{
return new Response(200, [], Twig::render($template, $vars, $app));
}
/**
* @return Request
*/
function request()
{
return App::request();
}
/**
* @param string|null $key
* @param $default
* @return array|mixed|null
*/
function config(string $key = null, $default = null)
{
return Config::get($key, $default);
}
/**
* @param string $name
* @param ...$parameters
* @return string
*/
function route(string $name, ...$parameters)
{
$route = Route::getByName($name);
if (!$route) {
return '';
}
if (!$parameters) {
return $route->url();
}
if (\is_array(\current($parameters))) {
$parameters = \current($parameters);
}
return $route->url($parameters);
}
/**
* @param mixed $key
* @param mixed $default
* @return mixed
*/
function session($key = null, $default = null)
{
$session = \request()->session();
if (null === $key) {
return $session;
}
if (\is_array($key)) {
$session->put($key);
return null;
}
if (\strpos($key, '.')) {
$key_array = \explode('.', $key);
$value = $session->all();
foreach ($key_array as $index) {
if (!isset($value[$index])) {
return $default;
}
$value = $value[$index];
}
return $value;
}
return $session->get($key, $default);
}
/**
* @param string $id
* @param array $parameters
* @param string|null $domain
* @param string|null $locale
* @return string
*/
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null)
{
$res = Translation::trans($id, $parameters, $domain, $locale);
return $res === '' ? $id : $res;
}
/**
* @param null|string $locale
* @return string
*/
function locale(string $locale = null)
{
if (!$locale) {
return Translation::getLocale();
}
Translation::setLocale($locale);
}
/**
* 404 not found
*
* @return Response
*/
function not_found()
{
return new Response(404, [], \file_get_contents(public_path() . '/404.html'));
}
/**
* Copy dir.
*
* @param string $source
* @param string $dest
* @param bool $overwrite
* @return void
*/
function copy_dir(string $source, string $dest, bool $overwrite = false)
{
if (\is_dir($source)) {
if (!is_dir($dest)) {
\mkdir($dest);
}
$files = \scandir($source);
foreach ($files as $file) {
if ($file !== "." && $file !== "..") {
\copy_dir("$source/$file", "$dest/$file");
}
}
} else if (\file_exists($source) && ($overwrite || !\file_exists($dest))) {
\copy($source, $dest);
}
}
/**
* Remove dir.
*
* @param string $dir
* @return bool
*/
function remove_dir(string $dir)
{
if (\is_link($dir) || \is_file($dir)) {
return \unlink($dir);
}
$files = \array_diff(\scandir($dir), array('.', '..'));
foreach ($files as $file) {
(\is_dir("$dir/$file") && !\is_link($dir)) ? \remove_dir("$dir/$file") : \unlink("$dir/$file");
}
return \rmdir($dir);
}
/**
* @param $worker
* @param $class
*/
function worker_bind($worker, $class)
{
$callback_map = [
'onConnect',
'onMessage',
'onClose',
'onError',
'onBufferFull',
'onBufferDrain',
'onWorkerStop',
'onWebSocketConnect'
];
foreach ($callback_map as $name) {
if (\method_exists($class, $name)) {
$worker->$name = [$class, $name];
}
}
if (\method_exists($class, 'onWorkerStart')) {
[$class, 'onWorkerStart']($worker);
}
}
/**
* @param $process_name
* @param $config
* @return void
*/
function worker_start($process_name, $config)
{
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
$property_map = [
'count',
'user',
'group',
'reloadable',
'reusePort',
'transport',
'protocol',
];
$worker->name = $process_name;
foreach ($property_map as $property) {
if (isset($config[$property])) {
$worker->$property = $config[$property];
}
}
$worker->onWorkerStart = function ($worker) use ($config) {
require_once \base_path() . '/support/bootstrap.php';
foreach ($config['services'] ?? [] as $server) {
if (!\class_exists($server['handler'])) {
echo "process error: class {$server['handler']} not exists\r\n";
continue;
}
$listen = new Worker($server['listen'] ?? null, $server['context'] ?? []);
if (isset($server['listen'])) {
echo "listen: {$server['listen']}\n";
}
$instance = Container::make($server['handler'], $server['constructor'] ?? []);
\worker_bind($listen, $instance);
$listen->listen();
}
if (isset($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);
}
};
}
/**
* Phar support.
* Compatible with the 'realpath' function in the phar file.
*
* @param string $file_path
* @return string
*/
function get_realpath(string $file_path): string
{
if (\strpos($file_path, 'phar://') === 0) {
return $file_path;
} else {
return \realpath($file_path);
}
}
/**
* @return bool
*/
function is_phar()
{
return \class_exists(\Phar::class, false) && Phar::running();
}
/**
* @return int
*/
function cpu_count()
{
// Windows does not support the number of processes setting.
if (\DIRECTORY_SEPARATOR === '\\') {
return 1;
}
$count = 4;
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');
}
}
return $count > 0 ? $count : 4;
}

View File

@@ -12,7 +12,7 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace support\View;
namespace support\view;
use Jenssegers\Blade\Blade as BladeView;
use Webman\View;
@@ -20,7 +20,7 @@ use Webman\View;
/**
* Class Blade
* composer require jenssegers/blade
* @package Support\View
* @package support\view
*/
class Blade implements View
{

View File

@@ -12,14 +12,14 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace support\View;
namespace support\view;
use Webman\View;
use Throwable;
/**
* Class Raw
* @package Support\View
* @package support\view
*/
class Raw implements View
{
@@ -51,14 +51,14 @@ class Raw implements View
$view_suffix = \config("{$config_prefix}view.options.view_suffix", 'html');
$app = $app === null ? $request->app : $app;
$base_view_path = $plugin ? \base_path() . "/plugin/$plugin/app" : \app_path();
$view_path = $app === '' ? "$base_view_path/view/$template.$view_suffix" : "$base_view_path/$app/view/$template.$view_suffix";
$__template_path__ = $app === '' ? "$base_view_path/view/$template.$view_suffix" : "$base_view_path/$app/view/$template.$view_suffix";
\extract(static::$_vars, \EXTR_SKIP);
\extract($vars, \EXTR_SKIP);
\extract(static::$_vars);
\extract($vars);
\ob_start();
// Try to include php file.
try {
include $view_path;
include $__template_path__;
} catch (Throwable $e) {
static::$_vars = [];
\ob_end_clean();

View File

@@ -12,14 +12,14 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace support\View;
namespace support\view;
use think\Template;
use Webman\View;
/**
* Class Blade
* @package Support\View
* @package support\view
*/
class ThinkPHP implements View
{

View File

@@ -12,7 +12,7 @@
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace support\View;
namespace support\view;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
@@ -20,7 +20,7 @@ use Webman\View;
/**
* Class Blade
* @package Support\View
* @package support\view
*/
class Twig implements View
{

View File

@@ -1,116 +0,0 @@
<?php
/**
* Start file for windows
*/
require_once __DIR__ . '/vendor/autoload.php';
use process\Monitor;
use support\App;
use Dotenv\Dotenv;
use Workerman\Worker;
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();
}
}
App::loadAllConfig(['route']);
$error_reporting = config('app.error_reporting');
if (isset($error_reporting)) {
error_reporting($error_reporting);
}
$runtime_process_path = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
if (!is_dir($runtime_process_path)) {
mkdir($runtime_process_path);
}
$process_files = [
__DIR__ . DIRECTORY_SEPARATOR . 'start.php'
];
foreach (config('process', []) as $process_name => $config) {
$process_files[] = write_process_file($runtime_process_path, $process_name, '');
}
foreach (config('plugin', []) as $firm => $projects) {
foreach ($projects as $name => $project) {
if (!is_array($project)) {
continue;
}
foreach ($project['process'] ?? [] as $process_name => $config) {
$process_files[] = write_process_file($runtime_process_path, $process_name, "$firm.$name");
}
}
foreach ($projects['process'] ?? [] as $process_name => $config) {
$process_files[] = write_process_file($runtime_process_path, $process_name, $firm);
}
}
function write_process_file($runtime_process_path, $process_name, $firm)
{
$process_param = $firm ? "plugin.$firm.$process_name" : $process_name;
$config_param = $firm ? "config('plugin.$firm.process')['$process_name']" : "config('process')['$process_name']";
$file_content = <<<EOF
<?php
require_once __DIR__ . '/../../vendor/autoload.php';
use Workerman\Worker;
use Webman\Config;
use support\App;
ini_set('display_errors', 'on');
error_reporting(E_ALL);
if (is_callable('opcache_reset')) {
opcache_reset();
}
App::loadAllConfig(['route']);
worker_start('$process_param', $config_param);
if (DIRECTORY_SEPARATOR != "/") {
Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
}
Worker::runAll();
EOF;
$process_file = $runtime_process_path . DIRECTORY_SEPARATOR . "start_$process_param.php";
file_put_contents($process_file, $file_content);
return $process_file;
}
if ($monitor_config = config('process.monitor.constructor')) {
$monitor = new Monitor(...array_values($monitor_config));
}
function popen_processes($process_files)
{
$cmd = "php " . implode(' ', $process_files);
$descriptorspec = [STDIN, STDOUT, STDOUT];
$resource = proc_open($cmd, $descriptorspec, $pipes);
if (!$resource) {
exit("Can not execute $cmd\r\n");
}
return $resource;
}
$resource = popen_processes($process_files);
echo "\r\n";
while (1) {
sleep(1);
if (!empty($monitor) && $monitor->checkAllFilesChange()) {
$status = proc_get_status($resource);
$pid = $status['pid'];
shell_exec("taskkill /F /T /PID $pid");
proc_close($resource);
$resource = popen_processes($process_files);
}
}