| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- <?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('plugin.admin.mysql');
- }
- /**
- * 获取SchemaBuilder
- * @return Builder
- */
- public static function schema(): Builder
- {
- return Db::schema('plugin.admin.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')['plugin.admin.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();
- }
- }
- }
|