Files
swiftadmin/support/helpers.php

555 lines
12 KiB
PHP
Raw Normal View History

2022-08-19 19:48:37 +08:00
<?php
2022-11-28 19:11:12 +08:00
2022-08-19 19:48:37 +08:00
/**
* 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
*/
2022-11-28 19:11:12 +08:00
use support\Container;
2022-08-19 19:48:37 +08:00
use support\Request;
use support\Response;
use support\Translation;
use support\view\Blade;
2023-04-25 20:11:49 +08:00
use support\view\Raw;
2022-08-19 19:48:37 +08:00
use support\view\ThinkPHP;
use support\view\Twig;
2023-04-25 20:11:49 +08:00
use Symfony\Component\VarDumper\Caster\ReflectionCaster;
use Symfony\Component\VarDumper\Cloner\VarCloner;
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
use Symfony\Component\VarDumper\Dumper\ContextualizedDumper;
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
2022-08-19 19:48:37 +08:00
use Webman\App;
use Webman\Config;
use Webman\Route;
2023-04-25 20:11:49 +08:00
use Workerman\Worker;
2022-11-28 19:11:12 +08:00
// Project base path
define('BASE_PATH', dirname(__DIR__));
2022-08-19 19:48:37 +08:00
/**
2022-11-28 19:11:12 +08:00
* return the program execute directory
* @param string $path
* @return string
*/
2023-04-25 20:11:49 +08:00
function run_path(string $path = ''): string
2022-11-28 19:11:12 +08:00
{
2023-04-25 20:11:49 +08:00
static $runPath = '';
if (!$runPath) {
$runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
2022-11-28 19:11:12 +08:00
}
2023-04-25 20:11:49 +08:00
return path_combine($runPath, $path);
2022-11-28 19:11:12 +08:00
}
/**
* if the param $path equal false,will return this program current execute directory
* @param string|false $path
2023-04-25 20:11:49 +08:00
* @return string
2022-08-19 19:48:37 +08:00
*/
2023-04-25 20:11:49 +08:00
function base_path($path = ''): string
2022-08-19 19:48:37 +08:00
{
2022-11-28 19:11:12 +08:00
if (false === $path) {
2023-04-25 20:11:49 +08:00
return run_path();
2022-08-19 19:48:37 +08:00
}
2023-04-25 20:11:49 +08:00
return path_combine(BASE_PATH, $path);
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* App path
2022-11-28 19:11:12 +08:00
* @param string $path
2022-08-19 19:48:37 +08:00
* @return string
*/
2023-04-25 20:11:49 +08:00
function app_path(string $path = ''): string
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Public path
2022-11-28 19:11:12 +08:00
* @param string $path
2022-08-19 19:48:37 +08:00
* @return string
*/
2023-04-25 20:11:49 +08:00
function public_path(string $path = ''): string
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
static $publicPath = '';
if (!$publicPath) {
$publicPath = \config('app.public_path') ?: run_path('public');
2022-08-19 19:48:37 +08:00
}
2023-04-25 20:11:49 +08:00
return path_combine($publicPath, $path);
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Config path
2022-11-28 19:11:12 +08:00
* @param string $path
2022-08-19 19:48:37 +08:00
* @return string
*/
2023-04-25 20:11:49 +08:00
function config_path(string $path = ''): string
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Runtime path
2022-11-28 19:11:12 +08:00
* @param string $path
2022-08-19 19:48:37 +08:00
* @return string
*/
2023-04-25 20:11:49 +08:00
function runtime_path(string $path = ''): string
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
static $runtimePath = '';
if (!$runtimePath) {
$runtimePath = \config('app.runtime_path') ?: run_path('runtime');
}
return path_combine($runtimePath, $path);
}
if (!function_exists('halt')) {
/**
* 调试变量并且中断输出
* @param mixed $vars 调试变量或者信息
*/
function halt(...$vars)
{
ob_start();
$cloner = new VarCloner();
$cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO);
$dumper = new HtmlDumper();
$dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]);
foreach ($vars as $var) {
$dumper->dump($cloner->cloneVar($var));
}
$ob_response = (string)ob_get_clean();
throw new \RuntimeException($ob_response, 600);
}
}
if (!function_exists('get_env')) {
/**
* Get environment variable
*/
function get_env($var)
{
$dir = str_replace('\\', '/', realpath(__DIR__ . '/../'));
$env_path = $dir . '/.env';
2023-04-26 15:19:26 +08:00
static $env_info = [];
if (is_file($env_path) && !$env_info) {
2023-04-26 10:36:10 +08:00
$env_info = parse_ini_file($env_path, true);
}
2023-04-25 20:11:49 +08:00
return $env_info[$var] ?? '';
2022-08-19 19:48:37 +08:00
}
}
/**
2023-04-25 20:11:49 +08:00
* Generate paths based on given information
* @param string $front
* @param string $back
* @return string
*/
function path_combine(string $front, string $back): string
{
return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
}
/**
* Response
2022-08-19 19:48:37 +08:00
* @param int $status
* @param array $headers
* @param string $body
* @return Response
*/
2023-04-25 20:11:49 +08:00
function response(string $body = '', int $status = 200, array $headers = []): Response
2022-08-19 19:48:37 +08:00
{
return new Response($status, $headers, $body);
}
/**
2023-04-25 20:11:49 +08:00
* Json response
2022-08-19 19:48:37 +08:00
* @param $data
* @param int $options
* @return Response
*/
2023-04-25 20:11:49 +08:00
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Xml response
2022-08-19 19:48:37 +08:00
* @param $xml
* @return Response
*/
2023-04-25 20:11:49 +08:00
function xml($xml): Response
2022-08-19 19:48:37 +08:00
{
if ($xml instanceof SimpleXMLElement) {
$xml = $xml->asXML();
}
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
}
/**
2023-04-25 20:11:49 +08:00
* Jsonp response
2022-08-19 19:48:37 +08:00
* @param $data
2023-04-25 20:11:49 +08:00
* @param string $callbackName
2022-08-19 19:48:37 +08:00
* @return Response
*/
2023-04-25 20:11:49 +08:00
function jsonp($data, string $callbackName = 'callback'): Response
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
if (!is_scalar($data) && null !== $data) {
$data = json_encode($data);
2022-08-19 19:48:37 +08:00
}
2023-04-25 20:11:49 +08:00
return new Response(200, [], "$callbackName($data)");
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Redirect response
2022-08-19 19:48:37 +08:00
* @param string $location
* @param int $status
* @param array $headers
* @return Response
*/
2023-04-25 20:11:49 +08:00
function redirect(string $location, int $status = 302, array $headers = []): Response
2022-08-19 19:48:37 +08:00
{
$response = new Response($status, ['Location' => $location]);
if (!empty($headers)) {
$response->withHeaders($headers);
}
return $response;
}
/**
2023-04-25 20:11:49 +08:00
* View response
* @param string $template
2022-08-19 19:48:37 +08:00
* @param array $vars
2023-04-25 20:11:49 +08:00
* @param string|null $app
* @param string|null $plugin
2022-08-19 19:48:37 +08:00
* @return Response
*/
2023-04-25 20:11:49 +08:00
function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
2022-08-19 19:48:37 +08:00
{
$request = \request();
2023-04-25 20:11:49 +08:00
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
2022-08-19 19:48:37 +08:00
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
2023-04-25 20:11:49 +08:00
return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Raw view response
2022-08-19 19:48:37 +08:00
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
* @throws Throwable
*/
2023-04-25 20:11:49 +08:00
function raw_view(string $template, array $vars = [], string $app = null): Response
2022-08-19 19:48:37 +08:00
{
return new Response(200, [], Raw::render($template, $vars, $app));
}
/**
2023-04-25 20:11:49 +08:00
* Blade view response
2022-08-19 19:48:37 +08:00
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
2023-04-25 20:11:49 +08:00
function blade_view(string $template, array $vars = [], string $app = null): Response
2022-08-19 19:48:37 +08:00
{
return new Response(200, [], Blade::render($template, $vars, $app));
}
/**
2023-04-25 20:11:49 +08:00
* Think view response
2022-08-19 19:48:37 +08:00
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
*/
2023-04-25 20:11:49 +08:00
function think_view(string $template, array $vars = [], string $app = null): Response
2022-08-19 19:48:37 +08:00
{
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
}
/**
2023-04-25 20:11:49 +08:00
* Twig view response
2022-08-19 19:48:37 +08:00
* @param string $template
* @param array $vars
* @param string|null $app
* @return Response
2023-04-25 20:11:49 +08:00
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
2022-08-19 19:48:37 +08:00
*/
2023-04-25 20:11:49 +08:00
function twig_view(string $template, array $vars = [], string $app = null): Response
2022-08-19 19:48:37 +08:00
{
return new Response(200, [], Twig::render($template, $vars, $app));
}
/**
2023-04-25 20:11:49 +08:00
* Get request
2022-11-28 19:11:12 +08:00
* @return \Webman\Http\Request|Request|null
2022-08-19 19:48:37 +08:00
*/
function request()
{
return App::request();
}
/**
2023-04-25 20:11:49 +08:00
* Get config
2022-08-19 19:48:37 +08:00
* @param string|null $key
* @param $default
* @return array|mixed|null
*/
function config(string $key = null, $default = null)
{
return Config::get($key, $default);
}
/**
2023-04-25 20:11:49 +08:00
* Create url
2022-08-19 19:48:37 +08:00
* @param string $name
* @param ...$parameters
* @return string
*/
2023-04-25 20:11:49 +08:00
function route(string $name, ...$parameters): string
2022-08-19 19:48:37 +08:00
{
$route = Route::getByName($name);
if (!$route) {
return '';
}
if (!$parameters) {
return $route->url();
}
2023-04-25 20:11:49 +08:00
if (is_array(current($parameters))) {
$parameters = current($parameters);
2022-08-19 19:48:37 +08:00
}
return $route->url($parameters);
}
/**
2023-04-25 20:11:49 +08:00
* Session
2022-08-19 19:48:37 +08:00
* @param mixed $key
* @param mixed $default
* @return mixed
*/
function session($key = null, $default = null)
{
$session = \request()->session();
if (null === $key) {
return $session;
}
2023-04-25 20:11:49 +08:00
if (is_array($key)) {
2022-08-19 19:48:37 +08:00
$session->put($key);
return null;
}
2023-04-25 20:11:49 +08:00
if (strpos($key, '.')) {
$keyArray = explode('.', $key);
2022-08-19 19:48:37 +08:00
$value = $session->all();
2023-04-25 20:11:49 +08:00
foreach ($keyArray as $index) {
2022-08-19 19:48:37 +08:00
if (!isset($value[$index])) {
return $default;
}
$value = $value[$index];
}
return $value;
}
return $session->get($key, $default);
}
/**
2023-04-25 20:11:49 +08:00
* Translation
2022-08-19 19:48:37 +08:00
* @param string $id
* @param array $parameters
* @param string|null $domain
* @param string|null $locale
* @return string
*/
2023-04-25 20:11:49 +08:00
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
2022-08-19 19:48:37 +08:00
{
$res = Translation::trans($id, $parameters, $domain, $locale);
return $res === '' ? $id : $res;
}
/**
2023-04-25 20:11:49 +08:00
* Locale
* @param string|null $locale
2022-08-19 19:48:37 +08:00
* @return string
*/
2023-04-25 20:11:49 +08:00
function locale(string $locale = null): string
2022-08-19 19:48:37 +08:00
{
if (!$locale) {
return Translation::getLocale();
}
Translation::setLocale($locale);
2023-04-25 20:11:49 +08:00
return $locale;
2022-08-19 19:48:37 +08:00
}
/**
* 404 not found
* @return Response
*/
2023-04-25 20:11:49 +08:00
function not_found(): Response
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Copy dir
2022-08-19 19:48:37 +08:00
* @param string $source
* @param string $dest
* @param bool $overwrite
* @return void
*/
function copy_dir(string $source, string $dest, bool $overwrite = false)
{
2023-04-25 20:11:49 +08:00
if (is_dir($source)) {
2022-08-19 19:48:37 +08:00
if (!is_dir($dest)) {
2023-04-25 20:11:49 +08:00
mkdir($dest);
2022-08-19 19:48:37 +08:00
}
2023-04-25 20:11:49 +08:00
$files = scandir($source);
2022-08-19 19:48:37 +08:00
foreach ($files as $file) {
if ($file !== "." && $file !== "..") {
2023-04-25 20:11:49 +08:00
copy_dir("$source/$file", "$dest/$file");
2022-08-19 19:48:37 +08:00
}
}
2023-04-25 20:11:49 +08:00
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
copy($source, $dest);
2022-08-19 19:48:37 +08:00
}
}
/**
2023-04-25 20:11:49 +08:00
* Remove dir
2022-08-19 19:48:37 +08:00
* @param string $dir
* @return bool
*/
2023-04-25 20:11:49 +08:00
function remove_dir(string $dir): bool
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
if (is_link($dir) || is_file($dir)) {
return unlink($dir);
2022-08-19 19:48:37 +08:00
}
2023-04-25 20:11:49 +08:00
$files = array_diff(scandir($dir), array('.', '..'));
2022-08-19 19:48:37 +08:00
foreach ($files as $file) {
2023-04-25 20:11:49 +08:00
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
2022-08-19 19:48:37 +08:00
}
2023-04-25 20:11:49 +08:00
return rmdir($dir);
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Bind worker
2022-08-19 19:48:37 +08:00
* @param $worker
* @param $class
*/
function worker_bind($worker, $class)
{
2023-04-25 20:11:49 +08:00
$callbackMap = [
2022-08-19 19:48:37 +08:00
'onConnect',
'onMessage',
'onClose',
'onError',
'onBufferFull',
'onBufferDrain',
'onWorkerStop',
2023-04-25 20:11:49 +08:00
'onWebSocketConnect',
'onWorkerReload'
2022-08-19 19:48:37 +08:00
];
2023-04-25 20:11:49 +08:00
foreach ($callbackMap as $name) {
if (method_exists($class, $name)) {
2022-08-19 19:48:37 +08:00
$worker->$name = [$class, $name];
}
}
2023-04-25 20:11:49 +08:00
if (method_exists($class, 'onWorkerStart')) {
call_user_func([$class, 'onWorkerStart'], $worker);
2022-08-19 19:48:37 +08:00
}
}
/**
2023-04-25 20:11:49 +08:00
* Start worker
* @param $processName
2022-08-19 19:48:37 +08:00
* @param $config
* @return void
*/
2023-04-25 20:11:49 +08:00
function worker_start($processName, $config)
2022-08-19 19:48:37 +08:00
{
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
2023-04-25 20:11:49 +08:00
$propertyMap = [
2022-08-19 19:48:37 +08:00
'count',
'user',
'group',
'reloadable',
'reusePort',
'transport',
'protocol',
];
2023-04-25 20:11:49 +08:00
$worker->name = $processName;
foreach ($propertyMap as $property) {
2022-08-19 19:48:37 +08:00
if (isset($config[$property])) {
$worker->$property = $config[$property];
}
}
$worker->onWorkerStart = function ($worker) use ($config) {
2023-04-25 20:11:49 +08:00
require_once base_path('/support/bootstrap.php');
2022-08-19 19:48:37 +08:00
if (isset($config['handler'])) {
2023-04-25 20:11:49 +08:00
if (!class_exists($config['handler'])) {
2022-08-19 19:48:37 +08:00
echo "process error: class {$config['handler']} not exists\r\n";
return;
}
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
2023-04-25 20:11:49 +08:00
worker_bind($worker, $instance);
2022-08-19 19:48:37 +08:00
}
};
}
/**
2023-04-25 20:11:49 +08:00
* Get realpath
* @param string $filePath
2022-08-19 19:48:37 +08:00
* @return string
*/
2023-04-25 20:11:49 +08:00
function get_realpath(string $filePath): string
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
if (strpos($filePath, 'phar://') === 0) {
return $filePath;
2022-08-19 19:48:37 +08:00
} else {
2023-04-25 20:11:49 +08:00
return realpath($filePath);
2022-08-19 19:48:37 +08:00
}
}
/**
2023-04-25 20:11:49 +08:00
* Is phar
2022-08-19 19:48:37 +08:00
* @return bool
*/
2023-04-25 20:11:49 +08:00
function is_phar(): bool
2022-08-19 19:48:37 +08:00
{
2023-04-25 20:11:49 +08:00
return class_exists(Phar::class, false) && Phar::running();
2022-08-19 19:48:37 +08:00
}
/**
2023-04-25 20:11:49 +08:00
* Get cpu count
2022-08-19 19:48:37 +08:00
* @return int
*/
2023-04-25 20:11:49 +08:00
function cpu_count(): int
2022-08-19 19:48:37 +08:00
{
// Windows does not support the number of processes setting.
2023-04-25 20:11:49 +08:00
if (DIRECTORY_SEPARATOR === '\\') {
2022-08-19 19:48:37 +08:00
return 1;
}
$count = 4;
2023-04-25 20:11:49 +08:00
if (is_callable('shell_exec')) {
if (strtolower(PHP_OS) === 'darwin') {
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
2022-08-19 19:48:37 +08:00
} else {
2023-04-25 20:11:49 +08:00
$count = (int)shell_exec('nproc');
2022-08-19 19:48:37 +08:00
}
}
return $count > 0 ? $count : 4;
}