1
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
namespace plugin\admin\app\common;
|
||||
|
||||
|
||||
use plugin\admin\app\model\Admin;
|
||||
use plugin\admin\app\model\AdminAccess;
|
||||
use plugin\admin\app\model\AdminRole;
|
||||
use plugin\admin\app\model\AdminRule;
|
||||
|
||||
class Auth
|
||||
{
|
||||
/**
|
||||
* 获取权限范围内的所有角色id
|
||||
* @param bool $with_self
|
||||
* @return array
|
||||
*/
|
||||
public static function getScopeRoleIds(bool $with_self = false): array
|
||||
{
|
||||
if (!$admin = admin()) {
|
||||
return [];
|
||||
}
|
||||
$role_ids = $admin['roles'];
|
||||
$rules = AdminRole::whereIn('id', $role_ids)->column('rules');//->toArray();
|
||||
if ($rules && in_array('*', $rules)) {
|
||||
return AdminRole::column('id');//->toArray();
|
||||
}
|
||||
|
||||
$roles = AdminRole::select();
|
||||
$tree = new Tree($roles);
|
||||
$descendants = $tree->getDescendant($role_ids, $with_self);
|
||||
return array_column($descendants, 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取权限范围内的所有管理员id
|
||||
* @param bool $with_self
|
||||
* @return array
|
||||
*/
|
||||
public static function getScopeAdminIds(bool $with_self = false): array
|
||||
{
|
||||
$role_ids = static::getScopeRoleIds();
|
||||
$admin_ids = AdminAccess::whereIn('role_id', $role_ids)->column('admin_id');//->toArray();
|
||||
if ($with_self) {
|
||||
$admin_ids[] = admin_id();
|
||||
}
|
||||
return array_unique($admin_ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容旧版本
|
||||
* @param int $admin_id
|
||||
* @deprecated
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupperAdmin(int $admin_id = 0): bool
|
||||
{
|
||||
return static::isSuperAdmin($admin_id);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是超级管理员
|
||||
* @param int $admin_id
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSuperAdmin(int $admin_id = null): bool
|
||||
{
|
||||
if(!$admin_id){
|
||||
$admin_id = admin()['id'];
|
||||
}
|
||||
if($admin_id <=1){
|
||||
return true;
|
||||
}
|
||||
if (!$admin_id) {
|
||||
if (!$roles = admin('roles')) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$roles = AdminAccess::where('admin_id', $admin_id)->column('role_id');
|
||||
}
|
||||
$rules = AdminRole::whereIn('id', $roles)->column('rules');
|
||||
return $rules && in_array('*', $rules);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
namespace plugin\admin\app\common;
|
||||
|
||||
|
||||
class Tree
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取完整的树结构,包含祖先节点
|
||||
*/
|
||||
const INCLUDE_ANCESTORS = 1;
|
||||
|
||||
/**
|
||||
* 获取部分树,不包含祖先节点
|
||||
*/
|
||||
const EXCLUDE_ANCESTORS = 0;
|
||||
|
||||
/**
|
||||
* 数据
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
/**
|
||||
* 哈希树
|
||||
* @var array
|
||||
*/
|
||||
protected $hashTree = [];
|
||||
|
||||
/**
|
||||
* 父级字段名
|
||||
* @var string
|
||||
*/
|
||||
protected $pidName = 'pid';
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param string $pid_name
|
||||
*/
|
||||
public function __construct($data, string $pid_name = 'pid')
|
||||
{
|
||||
$this->pidName = $pid_name;
|
||||
if (is_object($data) && method_exists($data, 'toArray')) {
|
||||
$this->data = $data->toArray();
|
||||
} else {
|
||||
$this->data = (array)$data;
|
||||
$this->data = array_map(function ($item) {
|
||||
if (is_object($item) && method_exists($item, 'toArray')) {
|
||||
return $item->toArray();
|
||||
}
|
||||
return $item;
|
||||
}, $this->data);
|
||||
}
|
||||
$this->hashTree = $this->getHashTree();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取子孙节点
|
||||
* @param array $include
|
||||
* @param bool $with_self
|
||||
* @return array
|
||||
*/
|
||||
public function getDescendant(array $include, bool $with_self = false): array
|
||||
{
|
||||
$items = [];
|
||||
foreach ($include as $id) {
|
||||
if (!isset($this->hashTree[$id])) {
|
||||
return [];
|
||||
}
|
||||
if ($with_self) {
|
||||
$item = $this->hashTree[$id];
|
||||
unset($item['children']);
|
||||
$items[$item['id']] = $item;
|
||||
}
|
||||
foreach ($this->hashTree[$id]['children'] ?? [] as $item) {
|
||||
unset($item['children']);
|
||||
$items[$item['id']] = $item;
|
||||
foreach ($this->getDescendant([$item['id']]) as $it) {
|
||||
$items[$it['id']] = $it;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_values($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取哈希树
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
protected function getHashTree(array $data = []): array
|
||||
{
|
||||
$data = $data ?: $this->data;
|
||||
$hash_tree = [];
|
||||
foreach ($data as $item) {
|
||||
$hash_tree[$item['id']] = $item;
|
||||
}
|
||||
foreach ($hash_tree as $index => $item) {
|
||||
if ($item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) {
|
||||
$hash_tree[$item[$this->pidName]]['children'][$hash_tree[$index]['id']] = &$hash_tree[$index];
|
||||
}
|
||||
}
|
||||
return $hash_tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取树
|
||||
* @param array $include
|
||||
* @param int $type
|
||||
* @return array|null
|
||||
*/
|
||||
public function getTree(array $include = [], int $type = 1): ?array
|
||||
{
|
||||
// $type === static::EXCLUDE_ANCESTORS
|
||||
if ($type === static::EXCLUDE_ANCESTORS) {
|
||||
$items = [];
|
||||
$include = array_unique($include);
|
||||
foreach ($include as $id) {
|
||||
if (!isset($this->hashTree[$id])) {
|
||||
return [];
|
||||
}
|
||||
$items[] = $this->hashTree[$id];
|
||||
}
|
||||
return static::arrayValues($items);
|
||||
}
|
||||
|
||||
// $type === static::INCLUDE_ANCESTORS
|
||||
$hash_tree = $this->hashTree;
|
||||
$items = [];
|
||||
if ($include) {
|
||||
$map = [];
|
||||
foreach ($include as $id) {
|
||||
if (!isset($hash_tree[$id])) {
|
||||
continue;
|
||||
}
|
||||
$item = $hash_tree[$id];
|
||||
$max_depth = 100;
|
||||
while ($max_depth-- > 0 && $item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) {
|
||||
$last_item = $item;
|
||||
$pid = $item[$this->pidName];
|
||||
$item = $hash_tree[$pid];
|
||||
$item_id = $item['id'];
|
||||
if (empty($map[$item_id])) {
|
||||
$map[$item_id] = 1;
|
||||
$hash_tree[$pid]['children'] = [];
|
||||
}
|
||||
$hash_tree[$pid]['children'][$last_item['id']] = $last_item;
|
||||
$item = $hash_tree[$pid];
|
||||
}
|
||||
$items[$item['id']] = $item;
|
||||
}
|
||||
} else {
|
||||
$items = $hash_tree;
|
||||
}
|
||||
$formatted_items = [];
|
||||
foreach ($items as $item) {
|
||||
if (!$item[$this->pidName] || !isset($hash_tree[$item[$this->pidName]])) {
|
||||
$formatted_items[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return static::arrayValues($formatted_items);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归重建数组下标
|
||||
* @param $array
|
||||
* @return array
|
||||
*/
|
||||
public static function arrayValues($array): array
|
||||
{
|
||||
if (!$array) {
|
||||
return [];
|
||||
}
|
||||
if (!isset($array['children'])) {
|
||||
$current = current($array);
|
||||
if (!is_array($current)) {
|
||||
return $array;
|
||||
}
|
||||
$tree = array_values($array);
|
||||
foreach ($tree as $index => $item) {
|
||||
$tree[$index] = static::arrayValues($item);
|
||||
}
|
||||
return $tree;
|
||||
}
|
||||
$array['children'] = array_values($array['children']);
|
||||
foreach ($array['children'] as $index => $child) {
|
||||
$array['children'][$index] = static::arrayValues($child);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\admin\app\common;
|
||||
|
||||
use process\Monitor;
|
||||
use Throwable;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Database\Schema\Builder;
|
||||
use plugin\admin\app\model\Option;
|
||||
use support\exception\BusinessException;
|
||||
use support\Db;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* 密码哈希
|
||||
* @param $password
|
||||
* @param string $algo
|
||||
* @return false|string|null
|
||||
*/
|
||||
public static function passwordHash($password, string $algo = PASSWORD_DEFAULT)
|
||||
{
|
||||
return password_hash($password, $algo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证密码哈希
|
||||
* @param $password
|
||||
* @param $hash
|
||||
* @return bool
|
||||
*/
|
||||
public static function passwordVerify(string $password, string $hash): bool
|
||||
{
|
||||
return password_verify($password, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取webman-admin数据库连接
|
||||
* @return Connection
|
||||
*/
|
||||
public static function db(): Connection
|
||||
{
|
||||
return Db::connection('mysql');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SchemaBuilder
|
||||
* @return Builder
|
||||
*/
|
||||
public static function schema(): Builder
|
||||
{
|
||||
return Db::schema('mysql');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取语义化时间
|
||||
* @param $time
|
||||
* @return false|string
|
||||
*/
|
||||
public static function humanDate($time)
|
||||
{
|
||||
$timestamp = is_numeric($time) ? $time : strtotime($time);
|
||||
$dur = time() - $timestamp;
|
||||
if ($dur < 0) {
|
||||
return date('Y-m-d', $timestamp);
|
||||
} else {
|
||||
if ($dur < 60) {
|
||||
return $dur . '秒前';
|
||||
} else {
|
||||
if ($dur < 3600) {
|
||||
return floor($dur / 60) . '分钟前';
|
||||
} else {
|
||||
if ($dur < 86400) {
|
||||
return floor($dur / 3600) . '小时前';
|
||||
} else {
|
||||
if ($dur < 2592000) { // 30天内
|
||||
return floor($dur / 86400) . '天前';
|
||||
} else {
|
||||
return date('Y-m-d', $timestamp);;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return date('Y-m-d', $timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文件大小
|
||||
* @param $file_size
|
||||
* @return string
|
||||
*/
|
||||
public static function formatBytes($file_size): string
|
||||
{
|
||||
$size = sprintf("%u", $file_size);
|
||||
if($size == 0) {
|
||||
return("0 Bytes");
|
||||
}
|
||||
$size_name = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
|
||||
return round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $size_name[$i];
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库字符串转义
|
||||
* @param $var
|
||||
* @return false|string
|
||||
*/
|
||||
public static function pdoQuote($var)
|
||||
{
|
||||
return Util::db()->getPdo()->quote($var, \PDO::PARAM_STR);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查表名是否合法
|
||||
* @param string $table
|
||||
* @return string
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function checkTableName(string $table): string
|
||||
{
|
||||
if (!preg_match('/^[a-zA-Z_0-9]+$/', $table)) {
|
||||
throw new BusinessException('表名不合法');
|
||||
}
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* 变量或数组中的元素只能是字母数字下划线组合
|
||||
* @param $var
|
||||
* @return mixed
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function filterAlphaNum($var)
|
||||
{
|
||||
$vars = (array)$var;
|
||||
array_walk_recursive($vars, function ($item) {
|
||||
if (is_string($item) && !preg_match('/^[a-zA-Z_0-9]+$/', $item)) {
|
||||
throw new BusinessException('参数不合法');
|
||||
}
|
||||
});
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* 变量或数组中的元素只能是字母数字
|
||||
* @param $var
|
||||
* @return mixed
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function filterNum($var)
|
||||
{
|
||||
$vars = (array)$var;
|
||||
array_walk_recursive($vars, function ($item) {
|
||||
if (is_string($item) && !preg_match('/^[0-9]+$/', $item)) {
|
||||
throw new BusinessException('参数不合法');
|
||||
}
|
||||
});
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否是合法URL Path
|
||||
* @param $var
|
||||
* @return string
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function filterUrlPath($var): string
|
||||
{
|
||||
if (!is_string($var) || !preg_match('/^[a-zA-Z0-9_\-\/&?.]+$/', $var)) {
|
||||
throw new BusinessException('参数不合法');
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否是合法Path
|
||||
* @param $var
|
||||
* @return string
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function filterPath($var): string
|
||||
{
|
||||
if (!is_string($var) || !preg_match('/^[a-zA-Z0-9_\-\/]+$/', $var)) {
|
||||
throw new BusinessException('参数不合法');
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
|
||||
/**
|
||||
* 类转换为url path
|
||||
* @param $controller_class
|
||||
* @return false|string
|
||||
*/
|
||||
static function controllerToUrlPath($controller_class)
|
||||
{
|
||||
$key = strtolower($controller_class);
|
||||
$action = '';
|
||||
if (strpos($key, '@')) {
|
||||
[$key, $action] = explode( '@', $key, 2);
|
||||
}
|
||||
$prefix = 'plugin';
|
||||
$paths = explode('\\', $key);
|
||||
if (count($paths) < 2) {
|
||||
return false;
|
||||
}
|
||||
$base = '';
|
||||
if (strpos($key, "$prefix\\") === 0) {
|
||||
if (count($paths) < 4) {
|
||||
return false;
|
||||
}
|
||||
array_shift($paths);
|
||||
$plugin = array_shift($paths);
|
||||
$base = "/app/$plugin/";
|
||||
}
|
||||
array_shift($paths);
|
||||
foreach ($paths as $index => $path) {
|
||||
if ($path === 'controller') {
|
||||
unset($paths[$index]);
|
||||
}
|
||||
}
|
||||
$suffix = 'controller';
|
||||
$code = $base . implode('/', $paths);
|
||||
if (substr($code, -strlen($suffix)) === $suffix) {
|
||||
$code = substr($code, 0, -strlen($suffix));
|
||||
}
|
||||
return $action ? "$code/$action" : $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为驼峰
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function camel(string $value): string
|
||||
{
|
||||
static $cache = [];
|
||||
$key = $value;
|
||||
|
||||
if (isset($cache[$key])) {
|
||||
return $cache[$key];
|
||||
}
|
||||
|
||||
$value = ucwords(str_replace(['-', '_'], ' ', $value));
|
||||
|
||||
return $cache[$key] = str_replace(' ', '', $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为小驼峰
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public static function smCamel($value): string
|
||||
{
|
||||
return lcfirst(static::camel($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取注释中第一行
|
||||
* @param $comment
|
||||
* @return false|mixed|string
|
||||
*/
|
||||
public static function getCommentFirstLine($comment)
|
||||
{
|
||||
if ($comment === false) {
|
||||
return false;
|
||||
}
|
||||
foreach (explode("\n", $comment) as $str) {
|
||||
if ($s = trim($str, "*/\ \t\n\r\0\x0B")) {
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
return $comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* 表单类型到插件的映射
|
||||
* @return \string[][]
|
||||
*/
|
||||
public static function methodControlMap(): array
|
||||
{
|
||||
return [
|
||||
//method=>[控件]
|
||||
'integer' => ['InputNumber'],
|
||||
'string' => ['Input'],
|
||||
'text' => ['TextArea'],
|
||||
'date' => ['DatePicker'],
|
||||
'enum' => ['Select'],
|
||||
'float' => ['Input'],
|
||||
|
||||
'tinyInteger' => ['InputNumber'],
|
||||
'smallInteger' => ['InputNumber'],
|
||||
'mediumInteger' => ['InputNumber'],
|
||||
'bigInteger' => ['InputNumber'],
|
||||
|
||||
'unsignedInteger' => ['InputNumber'],
|
||||
'unsignedTinyInteger' => ['InputNumber'],
|
||||
'unsignedSmallInteger' => ['InputNumber'],
|
||||
'unsignedMediumInteger' => ['InputNumber'],
|
||||
'unsignedBigInteger' => ['InputNumber'],
|
||||
|
||||
'decimal' => ['Input'],
|
||||
'double' => ['Input'],
|
||||
|
||||
'mediumText' => ['TextArea'],
|
||||
'longText' => ['TextArea'],
|
||||
|
||||
'dateTime' => ['DateTimePicker'],
|
||||
|
||||
'time' => ['DateTimePicker'],
|
||||
'timestamp' => ['DateTimePicker'],
|
||||
|
||||
'char' => ['Input'],
|
||||
|
||||
'binary' => ['Input'],
|
||||
|
||||
'json' => ['input']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库类型到插件的转换
|
||||
* @param $type
|
||||
* @return string
|
||||
*/
|
||||
public static function typeToControl($type): string
|
||||
{
|
||||
if (stripos($type, 'int') !== false) {
|
||||
return 'inputNumber';
|
||||
}
|
||||
if (stripos($type, 'time') !== false || stripos($type, 'date') !== false) {
|
||||
return 'dateTimePicker';
|
||||
}
|
||||
if (stripos($type, 'text') !== false) {
|
||||
return 'textArea';
|
||||
}
|
||||
if ($type === 'enum') {
|
||||
return 'select';
|
||||
}
|
||||
return 'input';
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库类型到表单类型的转换
|
||||
* @param $type
|
||||
* @param $unsigned
|
||||
* @return string
|
||||
*/
|
||||
public static function typeToMethod($type, $unsigned = false)
|
||||
{
|
||||
if (stripos($type, 'int') !== false) {
|
||||
$type = str_replace('int', 'Integer', $type);
|
||||
return $unsigned ? "unsigned" . ucfirst($type) : lcfirst($type);
|
||||
}
|
||||
$map = [
|
||||
'int' => 'integer',
|
||||
'varchar' => 'string',
|
||||
'mediumtext' => 'mediumText',
|
||||
'longtext' => 'longText',
|
||||
'datetime' => 'dateTime',
|
||||
];
|
||||
return $map[$type] ?? $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按表获取摘要
|
||||
* @param $table
|
||||
* @param null $section
|
||||
* @return array|mixed
|
||||
* @throws BusinessException
|
||||
*/
|
||||
public static function getSchema($table, $section = null)
|
||||
{
|
||||
Util::checkTableName($table);
|
||||
$database = config('database.connections')['mysql']['database'];
|
||||
$schema_raw = $section !== 'table' ? Util::db()->select("select * from information_schema.COLUMNS where TABLE_SCHEMA = '$database' and table_name = '$table' order by ORDINAL_POSITION") : [];
|
||||
$forms = [];
|
||||
$columns = [];
|
||||
foreach ($schema_raw as $item) {
|
||||
$field = $item->COLUMN_NAME;
|
||||
$columns[$field] = [
|
||||
'field' => $field,
|
||||
'type' => Util::typeToMethod($item->DATA_TYPE, (bool)strpos($item->COLUMN_TYPE, 'unsigned')),
|
||||
'comment' => $item->COLUMN_COMMENT,
|
||||
'default' => $item->COLUMN_DEFAULT,
|
||||
'length' => static::getLengthValue($item),
|
||||
'nullable' => $item->IS_NULLABLE !== 'NO',
|
||||
'primary_key' => $item->COLUMN_KEY === 'PRI',
|
||||
'auto_increment' => strpos($item->EXTRA, 'auto_increment') !== false
|
||||
];
|
||||
|
||||
$forms[$field] = [
|
||||
'field' => $field,
|
||||
'comment' => $item->COLUMN_COMMENT,
|
||||
'control' => static::typeToControl($item->DATA_TYPE),
|
||||
'form_show' => $item->COLUMN_KEY !== 'PRI',
|
||||
'list_show' => true,
|
||||
'enable_sort' => false,
|
||||
'searchable' => false,
|
||||
'search_type' => 'normal',
|
||||
'control_args' => '',
|
||||
];
|
||||
}
|
||||
$table_schema = $section == 'table' || !$section ? Util::db()->select("SELECT TABLE_COMMENT FROM information_schema.`TABLES` WHERE TABLE_SCHEMA='$database' and TABLE_NAME='$table'") : [];
|
||||
$indexes = !$section || in_array($section, ['keys', 'table']) ? Util::db()->select("SHOW INDEX FROM `$table`") : [];
|
||||
$keys = [];
|
||||
$primary_key = [];
|
||||
foreach ($indexes as $index) {
|
||||
$key_name = $index->Key_name;
|
||||
if ($key_name == 'PRIMARY') {
|
||||
$primary_key[] = $index->Column_name;
|
||||
continue;
|
||||
}
|
||||
if (!isset($keys[$key_name])) {
|
||||
$keys[$key_name] = [
|
||||
'name' => $key_name,
|
||||
'columns' => [],
|
||||
'type' => $index->Non_unique == 0 ? 'unique' : 'normal'
|
||||
];
|
||||
}
|
||||
$keys[$key_name]['columns'][] = $index->Column_name;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'table' => ['name' => $table, 'comment' => $table_schema[0]->TABLE_COMMENT ?? '', 'primary_key' => $primary_key],
|
||||
'columns' => $columns,
|
||||
'forms' => $forms,
|
||||
'keys' => array_reverse($keys, true)
|
||||
];
|
||||
|
||||
$schema = Option::where('name', "table_form_schema_$table")->value('value');
|
||||
$form_schema_map = $schema ? json_decode($schema, true) : [];
|
||||
|
||||
foreach ($data['forms'] as $field => $item) {
|
||||
if (isset($form_schema_map[$field])) {
|
||||
$data['forms'][$field] = $form_schema_map[$field];
|
||||
}
|
||||
}
|
||||
|
||||
return $section ? $data[$section] : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字段长度或默认值
|
||||
* @param $schema
|
||||
* @return mixed|string
|
||||
*/
|
||||
public static function getLengthValue($schema)
|
||||
{
|
||||
$type = $schema->DATA_TYPE;
|
||||
if (in_array($type, ['float', 'decimal', 'double'])) {
|
||||
return "{$schema->NUMERIC_PRECISION},{$schema->NUMERIC_SCALE}";
|
||||
}
|
||||
if ($type === 'enum') {
|
||||
return implode(',', array_map(function($item){
|
||||
return trim($item, "'");
|
||||
}, explode(',', substr($schema->COLUMN_TYPE, 5, -1))));
|
||||
}
|
||||
if (in_array($type, ['varchar', 'text', 'char'])) {
|
||||
return $schema->CHARACTER_MAXIMUM_LENGTH;
|
||||
}
|
||||
if (in_array($type, ['time', 'datetime', 'timestamp'])) {
|
||||
return $schema->CHARACTER_MAXIMUM_LENGTH;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取控件参数
|
||||
* @param $control
|
||||
* @param $control_args
|
||||
* @return array
|
||||
*/
|
||||
public static function getControlProps($control, $control_args): array
|
||||
{
|
||||
if (!$control_args) {
|
||||
return [];
|
||||
}
|
||||
$control = strtolower($control);
|
||||
$props = [];
|
||||
$split = explode(';', $control_args);
|
||||
foreach ($split as $item) {
|
||||
$pos = strpos($item, ':');
|
||||
if ($pos === false) {
|
||||
continue;
|
||||
}
|
||||
$name = trim(substr($item, 0, $pos));
|
||||
$values = trim(substr($item, $pos + 1));
|
||||
// values = a:v,c:d
|
||||
$pos = strpos($values, ':');
|
||||
if ($pos !== false && strpos($values, "#") !== 0) {
|
||||
$options = explode(',', $values);
|
||||
$values = [];
|
||||
foreach ($options as $option) {
|
||||
[$v, $n] = explode(':', $option);
|
||||
if (in_array($control, ['select', 'selectmulti', 'treeselect', 'treemultiselect']) && $name == 'data') {
|
||||
$values[] = ['value' => $v, 'name' => $n];
|
||||
} else {
|
||||
$values[$v] = $n;
|
||||
}
|
||||
}
|
||||
}
|
||||
$props[$name] = $values;
|
||||
}
|
||||
return $props;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个composer包的版本
|
||||
* @param string $package
|
||||
* @return mixed|string
|
||||
*/
|
||||
public static function getPackageVersion(string $package)
|
||||
{
|
||||
$installed_php = base_path('vendor/composer/installed.php');
|
||||
if (is_file($installed_php)) {
|
||||
$packages = include $installed_php;
|
||||
}
|
||||
return substr($packages['versions'][$package]['version'] ?? 'unknown ', 0, -2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reload webman
|
||||
* @return bool
|
||||
*/
|
||||
public static function reloadWebman()
|
||||
{
|
||||
if (function_exists('posix_kill')) {
|
||||
try {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
return true;
|
||||
} catch (Throwable $e) {}
|
||||
} else {
|
||||
Timer::add(1, function () {
|
||||
Worker::stopAll();
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause file monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function pauseFileMonitor()
|
||||
{
|
||||
if (method_exists(Monitor::class, 'pause')) {
|
||||
Monitor::pause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume file monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function resumeFileMonitor()
|
||||
{
|
||||
if (method_exists(Monitor::class, 'resume')) {
|
||||
Monitor::resume();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user