cms-manage/app/common.php

1242 lines
34 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// 应用公共文件
// 数族分组
use app\exception\TokenException;
use EasySwoole\Jwt\Jwt;
function getArrayGroupBy($data, $key): array
{
$result = [];
foreach ($data as $value) {
if (array_key_exists($key, $value)) {
$groupValue = $value[$key];
if (!array_key_exists($groupValue, $result)) {
$result[$groupValue] = array();
}
$result[$groupValue][] = $value;
}
}
return $result;
}
function strToUtf8($str)
{
$encode = mb_detect_encoding($str, array('CP936', "ASCII", "GB2312", "GBK", 'UTF-8', 'BIG5'));
if ($encode == 'UTF-8') {
return $str;
} else {
return mb_convert_encoding($str, 'UTF-8', $encode);
}
}
/**
* 对富文本信息中的数据
* 匹配出所有的 <img> 标签的 src属性
* @param string $contentStr 富文本字符串
* @return array
*
*/
function getPatternMatchImages(string $contentStr = ''): array
{
$imgSrcArr = [];
//首先将富文本字符串中的 img 标签进行匹配
$pattern_imgTag = '/<img\b.*?(?:\>|\/>)/i';
preg_match_all($pattern_imgTag, $contentStr, $matchIMG);
if (isset($matchIMG[0])) {
foreach ($matchIMG[0] as $key => $imgTag) {
//进一步提取 img标签中的 src属性信息
$pattern_src = '/\bsrc\b\s*=\s*[\'\"]?([^\'\"]*)[\'\"]?/i';
preg_match_all($pattern_src, $imgTag, $matchSrc);
if (isset($matchSrc[1])) {
foreach ($matchSrc[1] as $src) {
//将匹配到的src信息压入数组
$imgSrcArr[] = $src;
}
}
}
}
//$pattern= '/<img\b.+\bsrc\b\s*=\s*[\'\"]([^\'\"]*)[\'\"]/iU';
return $imgSrcArr;
}
// 获取文件夹下文件数量
function getFileNumber($path): int
{
$handle = opendir($path);
$i = 0;
while (false !== $file = (readdir($handle))) {
if ($file !== '.' && $file != '..') {
$i++;
}
}
closedir($handle);
return $i;
}
// 手机版访问
function isMobile(): bool
{
return request()->isMobile();
}
// 按照字符串个数切割字符串
function hcSubstr($str, $len, $start = 0): string
{
if (empty($str)) {
return '';
}
//返回字符串中的前100字符串长度的字符
return mb_substr($str, $start, $len, 'utf-8');
}
// sql切割
function hcSplitSql($file, $prefix, $charset = 'utf8mb4', $defaultTablePre = '$prefix$', $defaultCharset = 'utf8mb4')
{
if (file_exists($file)) {
//读取SQL文件
$sql = file_get_contents($file);
$sql = str_replace("\r", "\n", $sql);
$sql = str_replace("BEGIN;\n", '', $sql);//兼容 navicat 导出的 insert 语句
$sql = str_replace("COMMIT;\n", '', $sql);//兼容 navicat 导出的 insert 语句
$sql = str_replace($defaultCharset, $charset, $sql);
$sql = trim($sql);
//替换表前缀
$sql = str_replace("{$defaultTablePre}", "{$prefix}", $sql);
$sqls = explode(";\n", $sql);
return $sqls;
}
return [];
}
function sp_testwrite($d)
{
$tfile = "_test.txt";
$fp = @fopen($d . "/" . $tfile, "w");
if (!$fp) {
return false;
}
fclose($fp);
$rs = @unlink($d . "/" . $tfile);
if ($rs) {
return true;
}
return false;
}
function sp_dir_create($path, $mode = 0777)
{
if (is_dir($path))
return true;
$ftp_enable = 0;
$path = sp_dir_path($path);
$temp = explode('/', $path);
$cur_dir = '';
$max = count($temp) - 1;
for ($i = 0; $i < $max; $i++) {
$cur_dir .= $temp[$i] . '/';
if (@is_dir($cur_dir))
continue;
@mkdir($cur_dir, 0777, true);
@chmod($cur_dir, 0777);
}
return is_dir($path);
}
function sp_dir_path($path)
{
$path = str_replace('\\', '/', $path);
if (substr($path, -1) != '/')
$path = $path . '/';
return $path;
}
function sp_execute_sql($db, $sql)
{
$sql = trim($sql);
if (substr($sql, 0, 12) == 'CREATE TABLE') {
$table_name = preg_replace("/^CREATE TABLE `(\w+)` .*/s", "\\1", $sql);;
$msg = "创建数据表 {$table_name} ";
try {
$db->execute($sql);
return [
'type' => 1, // 创建表
'error' => 0,
'message' => $msg . '成功!'
];
} catch (\Exception $e) {
return [
'type' => 1, // 创建表
'error' => 1,
'message' => $msg . '失败!',
'exception' => $e->getMessage()
];
}
} else {
try {
$db->execute($sql);
return [
'type' => 2, // 执行sql语句
'error' => 0,
'message' => 'SQL执行成功!'
];
} catch (\Exception $e) {
return [
'type' => 2, // 执行sql语句
'error' => 1,
'message' => 'SQL执行失败',
'exception' => $e->getMessage()
];
}
}
}
function hcInstalled(): bool
{
return file_exists(CMS_ROOT . '/public/system_file/install.lock');
}
function createInstallFile()
{
@file_put_contents(CMS_ROOT . '/public/system_file/install.lock', file_get_contents(CMS_ROOT .'/version'));
}
function updateVersion()
{
if (file_get_contents(CMS_ROOT .'/version') != @file_get_contents(CMS_ROOT .'/public/system_file/install.lock')) {
createInstallFile();
}
}
/**
* @throws \app\exception\ModelException
* @throws \app\exception\ModelEmptyException
*/
function hcUrl($url, $vars, $suffix = true, $domain = false): \think\route\Url
{
$url = strtolower($url);
if (false === strpos($url, '://') && 0 !== strpos($url, '/')) {
$info = parse_url($url);
$url = !empty($info['path']) ? $info['path'] : '';
if (isset($info['fragment'])) {
// 解析锚点
$anchor = $info['fragment'];
if (false !== strpos($anchor, '?')) {
// 解析参数
list($anchor, $info['query']) = explode('?', $anchor, 2);
}
if (false !== strpos($anchor, '@')) {
// 解析域名
list($anchor, $domain) = explode('@', $anchor, 2);
}
} elseif (strpos($url, '@') && false === strpos($url, '\\')) {
// 解析域名
list($url, $domain) = explode('@', $url, 2);
}
}
if (0 == strpos($url, '/')) {
$url = ltrim($url, '/');
}
// 解析参数
if (is_string($vars)) {
// aaa=1&bbb=2 转换成数组
parse_str($vars, $vars);
}
if (isset($info['query'])) {
// 解析地址里面参数 合并到vars
parse_str($info['query'], $params);
$vars = array_merge($params, $vars);
}
if (!empty($anchor)) {
$url = $url . '#' . $anchor;
}
if ($url == 'list/index' && isset($vars['id'])) {
$url = $url . '?id=' . $vars['id'];
unset($vars['id']);
}
if ($url == 'detail/index' && isset($vars['cid'])) {
$url = $url . '?cid=' . $vars['cid'];
unset($vars['cid']);
}
if ($url == 'tag/index') {
$url = $url . '?id=' . $vars['id'];
}
return url($url, $vars, $suffix, $domain);
}
function optEventLog($id, $title, $operation)
{
if (is_array($id)) {
$id = implode(',', $id);
}
$optAdmin = request()->admin;
event("AdminOptLog", [
'admin_id' => $optAdmin['uid'],
'admin_name' => $optAdmin['name'],
'title' => $title . lang("管理"),
"content" => $operation . $title . ',' . $title . lang('ID为') . $id,
]);
}
/**
* 判断是否为windows系统
* @return bool
*/
function windows_os(): bool
{
return PHP_OS_FAMILY === 'Windows';
}
function is_directory($directory): bool
{
return is_dir($directory);
}
// 获取文件后缀
function getFileExt($str): string
{
return strtolower(pathinfo($str, PATHINFO_EXTENSION));
}
/**
* 返回文件格式
* @param string $str 文件名
* @return string 文件格式
*/
function fileFormat(string $str): string
{
// 取文件后缀名
$str = getFileExt($str);
// 图片格式
$image = array('webp', 'jpg', 'png', 'ico', 'bmp', 'gif', 'tif', 'pcx', 'tga', 'bmp', 'pxc', 'tiff', 'jpeg', 'exif', 'fpx', 'svg', 'psd', 'cdr', 'pcd', 'dxf', 'ufo', 'eps', 'ai', 'hdri');
// 视频格式
$video = array('mp4', 'avi', '3gp', 'rmvb', 'wmv', 'mkv', 'mpg', 'vob', 'mov', 'flv', 'swf', 'ape', 'wma', 'aac', 'mmf', 'amr', 'm4a', 'm4r', 'ogg', 'wav', 'wavpack', 'm4v', 'webm');
// 音频格式
$audio = array('mp3', 'mpeg', 'wma', 'mid', 'cd', 'wave', 'aiff', 'mpeg-4', 'midi', 'flac', 'acc', 'ape', 'amr');
// 压缩格式
$zip = array('rar', 'zip', 'tar', 'cab', 'uue', 'jar', 'iso', 'z', '7-zip', 'ace', 'lzh', 'arj', 'gzip', 'bz2', 'tz');
// 文档格式
$text = array('exe', 'doc', 'ppt', 'xls', 'wps', 'txt', 'lrc', 'wfs', 'torrent', 'html', 'htm', 'java', 'js', 'css', 'less', 'php', 'pdf', 'pps', 'host', 'box', 'docx', 'word', 'perfect', 'dot', 'dsf', 'efe', 'ini', 'json', 'lnk', 'log', 'msi', 'ost', 'pcs', 'tmp', 'xlsb','ttf', 'eot','woff','woff2');
// 匹配不同的结果
switch ($str) {
case in_array($str, $image):
return 'image';
case in_array($str, $video):
return 'video';
case in_array($str, $zip):
return 'zip';
case in_array($str, $audio):
return 'audio';
default:
return 'file';
}
}
/**
* 获取网站跟目录
* @return string
*/
function hcGetRoot(): string
{
$root = request()->root();
$root = str_replace("//", '/', $root);
$root = str_replace('/index.php', '', $root);
if (defined('APP_NAMESPACE') && APP_NAMESPACE == 'api') {
$root = preg_replace('/\/api$/', '', $root);
}
return rtrim($root, '/');
}
/**
* 扫描路径下所有文件包括子目录
* @param $dir
* @return array
*/
function scanSubDir($dir): array
{
// $dir = ltrim($dir, "/");
$dirs = [];
$subDirs = hcScanDir("$dir/*", GLOB_ONLYDIR);
if (!empty($subDirs)) {
foreach ($subDirs as $subDir) {
$subDir = "$dir/$subDir";
array_push($dirs, $subDir);
$subDirSubDirs = scanSubDir($subDir);
if (!empty($subDirSubDirs)) {
$dirs = array_merge($dirs, $subDirSubDirs);
}
}
}
return $dirs;
}
/**
* 判断文件是否存在
* @param $filename
* @return bool
*/
function hcFileExist($filename): bool
{
if (is_file($filename)) {
if (env('app_debug')) {
if (basename(realpath($filename)) != basename($filename))
return false;
}
return true;
}
return false;
}
/**
* 扫描路径下的文件
* @param $pattern
* @param null $flags
* @return array
*/
function hcScanDir($pattern, $flags = null): array
{
$files = glob($pattern, $flags);
if (empty($files)) {
$files = [];
} else {
$files = array_map('basename', $files);
}
return $files;
}
/**
* 小驼峰格式
*
* @param string $uncamelized_words
* @param string $separator
* @return string
*/
function camelize(string $uncamelized_words, string $separator = '_'): string
{
$uncamelized_words = $separator . str_replace($separator, " ", strtolower($uncamelized_words));
return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator);
}
/**
* 下划线格式
*
* @param string $camelCaps
* @param string $separator
* @return string
*/
function uncamelize(string $camelCaps, string $separator = '_'): string
{
return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
}
/**
* 模型内统一数据返回
* @param $code
* @param string $msg
* @param array $data
* @return array
*/
function dataReturn($code, $msg = 'success', $data = [])
{
return ['code' => $code, 'data' => $data, 'msg' => $msg];
}
/**
* 统一返回json数据
* @param $code
* @param string $msg
* @param $data
* @return \think\response\Json
*/
function jsonReturn($code, string $msg = 'success', $data = []): \think\response\Json
{
return json(['code' => $code, 'data' => $data, 'msg' => $msg]);
}
/**
* 生成用户密码
* @param $password
* @param string $salt
* @return string
*/
function makePassword($password, string $salt = ''): string
{
if (empty($salt)) {
$salt = config('system.salt');
}
return sha1(md5($password . $salt));
}
/**
* 校验密码
* @param $inputPassword
* @param $dbPassword
* @param string $salt
* @return bool
*/
function checkPassword($inputPassword, $dbPassword, string $salt = ''): bool
{
if (makePassword($inputPassword, $salt) == $dbPassword) {
return true;
}
return false;
}
/**
* 解析token中简短的用户信息
* @param $token
* @return array
*/
function getUserSimpleInfo($token): array
{
try {
$token = (new \Lcobucci\JWT\Parser())->parse($token);
} catch (\Exception $e) {
return dataReturn(-1, $e->getMessage());
}
$data = new \Lcobucci\JWT\ValidationData();
$data->setIssuer($token->getClaim('iss'));
$data->setAudience($token->getClaim('aud'));
$data->setId($token->getClaim('jti'));
if (!$token->validate($data)) {
return dataReturn(-2, 'token validate');
}
return dataReturn(0, '', [
'uid' => $token->getClaim('uid'),
'name' => $token->getClaim('name'),
'seller_id' => $token->getClaim('seller_id'),
]);
}
/**
* 从头部获取token
* @return bool|string
*/
function getHeaderToken()
{
$token = '';
$authorization = request()->header('authorization');
if (!empty($authorization)) {
$token = substr($authorization, 7);
}
return $token;
}
/**
* 统一分页返回
* @param $list
* @return array
*/
function pageReturn($list): array
{
if (0 == $list['code']) {
return ['code' => 0, 'msg' => 'ok', 'count' => $list['data']->total(), 'data' => $list['data']->all()];
}
return ['code' => 0, 'msg' => 'ok', 'count' => 0, 'data' => []];
}
// 引用实现无限分类
function generate(array $data, $flag = false): array
{
$data = getColumnForKeyArray($data, 'id');
$tree = [];
foreach ($data as $k => $v) {
if (isset($data[$v['parent_id']])) {
$data[$v['parent_id']]['children'][] = &$data[$k];
} else {
$tree[] = &$data[$k];
}
}
return $tree;
}
// 数组值作为键
function getColumnForKeyArray(array $data, string $key): array
{
$item = [];
foreach ($data as $val) {
if (!array_key_exists($key, $val)) {
break;
}
$val['children'] = [];
$item[$val[$key]] = $val;
}
return $item;
}
// 自定义树形结构层数
function makeTreeWithMaxLevel($data, $pid = 0, $maxLevel = 0, $level = 1): array
{
$tree = array();
foreach ($data as $key => $value) {
if ($value['parent_id'] == $pid) {
$value['level'] = $level;
unset($data[$key]);
if ($maxLevel === 0 || $maxLevel > $level) {
$value['children'] = makeTreeWithMaxLevel($data, $value['id'], $maxLevel, $level + 1);
} else {
$value['children'] = [];
}
$tree[] = $value;
}
}
return $tree;
}
/**
* // 递归实现无限分类
*
* @param $data
* @param int $pid
* @param int $level
* @return array
*/
function makeTree($data, int $pid = 0, int $level = 0): array
{
$tree = array();
foreach ($data as $key => $value) {
$value['children'] = [];
if ($value['parent_id'] == $pid) {
$value['level'] = $level;
unset($data[$key]);
$value['children'] = makeTree($data, $value['id'], $level + 1);
$tree[] = $value;
}
}
return $tree;
}
/**
* 获取某月所有时间
* @param string $time 某天时间戳
* @param string $format 转换的时间格式
* @return array
*/
function getMonth($time = '', $format = 'Y-m-d')
{
$time = $time != '' ? $time : time();
// 获取当前周几
$week = date('d', $time);
$date = [];
for ($i = 1; $i <= date('t', $time); $i++) {
$date[date($format, strtotime('+' . ($i - $week) . ' days', $time))] = 0;
}
return $date;
}
/**
* curl post数据
* @param $url
* @param $postData
* @return array
*/
function curlPost($url, $postData)
{
// 初始化
$curl = curl_init();
// 设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
// 设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 超时设置
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
// 超时设置,以毫秒为单位
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
// 设置post方式提交
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
// 执行命令
$data = curl_exec($curl);
curl_close($curl);
return dataReturn(0, '成功', $data);
}
/**
* curl get 请求
* @param $url
* @return array
*/
function curlGet($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
// $SSL = substr($url, 0, 8) == "https://" ? true : false;
// if ($SSL) {
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 信任任何证书
// curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // 检查证书中是否设置域名
// }
$data = curl_exec($ch);
curl_close($ch);
return dataReturn(0, '成功', $data);
}
/**
* 两个日期间全部的数据
* @param $start
* @param $end
* @return array
*/
function getBetweenDate($start, $end)
{
$returnDate = [];
$dtStart = strtotime($start);
$dtEnd = strtotime($end);
while ($dtStart <= $dtEnd) {
$returnDate[] = date('m-d', $dtStart);
$dtStart = strtotime('+1 day', $dtStart);
}
return $returnDate;
}
/**
* 获取树形结构指定值子级
* @param $tree
* @param $name
* @param $value
* @return array
*/
function getTreeDataValue($tree, $name, $value)
{
$resTree = array();
foreach ($tree as $item) {
if ($item[$name] == $value) {
$resTree[] = $item[$name];
if (is_array($item) && isset($item['children'])) {
$resTree = array_merge($resTree, getTreeData($item['children'], $name));
}
} else {
if (is_array($item) && isset($item['children'])) {
$resTree = array_merge($resTree, getTreeDataValue($item['children'], $name, $value));
}
}
}
return $resTree;
}
/**
* 获取树形结构指定值
* @param $tree
* @param $name
* @param $value
* @return array
*/
function getTreeData($tree, $name)
{
$resTree = array();
foreach ($tree as $item) {
$resTree[] = $item[$name];
if (is_array($item) && isset($item['children'])) {
$resTree = array_merge($resTree, getTreeData($item['children'], $name));
}
}
return $resTree;
}
/**
* 生成下载表格
* @param $fileName
* @param $sheetName
* @param $data
* @param $matchedData
* @return array
*/
function createDownloadExcel($fileName, $sheetName, $head, $data, $matchedData)
{
$config = [
'path' => config('suwork.excel_url'),
];
$fileName = $fileName . date('Y_m_d_H_i') . '.xlsx';
$xlsxObject = new \Vtiful\Kernel\Excel($config);
$formatData = [];
foreach ($data as $key => $value) {
foreach ($matchedData as $k => $val) {
if (isset($value[$k])) {
if (is_array($val)) {
if (isset($val[$value[$k]])) {
$formatData[$key][] = $val[$value[$k]];
} else {
$formatData[$key][] = '';
}
} else {
$formatData[$key][] = $value[$k];
}
} else {
$formatData[$key][] = '';
}
}
}
$formatData = array_values($formatData);
$filePath = $xlsxObject->fileName($fileName, $sheetName)
->header($head)
->data($formatData)
->output();
// Set Header
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header('Content-Disposition: attachment;filename="' . $fileName . '"');
header('Content-Length: ' . filesize($filePath));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Cache-Control: max-age=0');
header('Pragma: public');
ob_clean();
flush();
if (copy($filePath, 'php://output') === false) {
return jsonReturn(-1, '');
}
// Delete temporary file
@unlink($filePath);
die();
}
/**
* 参数过滤
* @param $class
* @return array
* @throws array
*/
function requestFilter($class)
{
try {
$class = new \ReflectionClass($class);
$properties = $class->getProperties();
$propertiesMap = [];
foreach ($properties as $vo) {
$propertiesMap[] = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $vo->name));
}
return \think\facade\Request::only($propertiesMap);
} catch (\ReflectionException $e) {
return [];
}
}
/**
* 获取设备信息
* @param $ua
* @return array
*/
function getDeviceInfo($ua)
{
$deviceOs = '未知设备';
$deviceVersion = '未知版本';
// $ua = $_SERVER['HTTP_USER_AGENT'];
if (strpos($ua, 'Android') !== false) {
preg_match("/(?<=Android )[\d\.]{1,}/", $ua, $version);
$deviceOs = 'Android';
$deviceVersion = $version[0];
} elseif (strpos($ua, 'iPhone') !== false) {
preg_match("/(?<=CPU iPhone OS )[\d\_]{1,}/", $ua, $version);
$deviceOs = 'iPhone';
$deviceVersion = str_replace('_', '.', $version[0]);
} elseif (strpos($ua, 'iPad') !== false) {
preg_match("/(?<=CPU OS )[\d\_]{1,}/", $ua, $version);
$deviceOs = 'iPad';
$deviceVersion = str_replace('_', '.', $version[0]);
} elseif (preg_match('/OmniWeb\/(v*)([^\s|;]+)/i', $ua, $regs)) {
$deviceOs = 'OmniWeb';
$deviceVersion = $regs[2];
} elseif (preg_match('/Netscape([\d]*)\/([^\s]+)/i', $ua, $regs)) {
$deviceOs = 'Netscape';
$deviceVersion = $regs[2];
} elseif (preg_match('/safari\/([^\s]+)/i', $ua, $regs) && !preg_match('/Chrome\/([^\s]+)/i', $ua, $regs2)) {
$deviceOs = 'Safari';
$deviceVersion = $regs[1];
} elseif (preg_match('/MSIE\s([^\s|;]+)/i', $ua, $regs)) {
$deviceOs = 'Internet Explorer';
$deviceVersion = $regs[1];
} elseif (preg_match('/Opera[\s|\/]([^\s]+)/i', $ua, $regs)) {
$deviceOs = 'Opera';
$deviceVersion = $regs[1];
} elseif (preg_match('/NetCaptor\s([^\s|;]+)/i', $ua, $regs)) {
$deviceOs = '(Internet Explorer) NetCaptor';
$deviceVersion = $regs[1];
} elseif (preg_match('/Maxthon/i', $ua, $regs)) {
$deviceOs = '(Internet Explorer) Maxthon';
$deviceVersion = '';
} elseif (preg_match('/360SE/i', $ua, $regs)) {
$deviceOs = '(Internet Explorer) 360SE';
$deviceVersion = '';
} elseif (preg_match('/SE 2.x/i', $ua, $regs)) {
$deviceOs = '(Internet Explorer) 搜狗';
$deviceVersion = '';
} elseif (preg_match('/FireFox\/([^\s]+)/i', $ua, $regs)) {
$deviceOs = 'FireFox';
$deviceVersion = $regs[1];
} elseif (preg_match('/Lynx\/([^\s]+)/i', $ua, $regs)) {
$deviceOs = 'Lynx';
$deviceVersion = $regs[1];
} elseif (preg_match('/Chrome\/([^\s]+)/i', $ua, $regs)) {
$deviceOs = 'Chrome';
$deviceVersion = $regs[1];
} elseif (strpos($ua, 'Postman') !== false) {
$deviceOs = 'Postman';
$deviceVersion = '';
}
return [
'deviceOs' => $deviceOs,
'deviceVersion' => $deviceVersion
];
}
/**
* 根据ip定位
* @param $ip
* @param $type
* @return string | array
* @throws Exception
*/
function getLocationByIp($ip, $type = 1)
{
$ip2region = new \Ip2Region();
$info = $ip2region->btreeSearch($ip);
if (empty($info) || empty($info['region'])) {
return ['province' => '未知', 'city' => '未知'];
}
$info = explode('|', $info['region']);
$address = '';
foreach ($info as $vo) {
if ('0' !== $vo) {
$address .= $vo . '-';
}
}
if (2 == $type) {
if (empty(array_filter($info))) {
return ['province' => '未知', 'city' => '未知'];
}
return ['province' => $info['2'], 'city' => $info['3']];
}
return rtrim($address, '-');
}
/**
* 快速排序
* @param $arr
*/
function quickSort(&$arr)
{
$length = count($arr);
if ($length <= 1) {
return;
}
$middle = $arr[0];
$left = [];
$right = [];
for ($i = 1; $i < $length; $i++) {
if ($middle['pivot']['sort'] < $arr[$i]['pivot']['sort']) {
$right[] = $arr[$i];
} else {
$left[] = $arr[$i];
}
}
quickSort($left);
quickSort($right);
$arr = array_merge($left, [$middle], $right);
// return $arr;
}
function makeFormTable($table)
{
return config('database.connections.mysql.prefix') . 'diyform_' . $table;
}
/**
* 获取当前请求所对应的语言
* @return string
*/
function setLang(): string
{
$baseUrl = trim(\request()->baseUrl(), '/');
$firstPath = explode('/', $baseUrl)[0];
$langArr = config('system.lang');
if (empty($firstPath) || !in_array($firstPath, $langArr)) {
$firstPath = config('lang.default_lang');
}
return $firstPath;
}
/**
* 字符串命名风格转换
* type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
* @param string $name 字符串
* @param integer $type 转换类型
* @param bool $ucfirst 首字母是否大写(驼峰规则)
* @return string
*/
function parse_name($name, $type = 0, $ucfirst = true)
{
if ($type) {
$name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
return strtoupper($match[1]);
}, $name);
return $ucfirst ? ucfirst($name) : lcfirst($name);
}
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
}
/**
* 获取插件类名
* @param string $name 插件名
* @return string
*/
function get_plugin_class($name)
{
$name = ucwords($name);
$pluginDir = parse_name($name);
$class = "plugins\\{$pluginDir}\\{$name}Plugin";
return $class;
}
function url_root($url = "")
{
$dual_host = array('aaa.pro', 'ac.cn', 'ac.kr', 'ac.mu', 'aca.pro', 'acct.pro', 'ae.org', 'ah.cn', 'ar.com', 'avocat.pro', 'bar.pro', 'biz.ki', 'biz.pl', 'bj.cn', 'br.com', 'busan.kr', 'chungbuk.kr', 'chungnam.kr', 'club.tw', 'cn.com', 'co.ag', 'co.am', 'co.at', 'co.bz', 'co.cm', 'co.com', 'co.gg', 'co.gl', 'co.gy', 'co.il', 'co.im', 'co.in', 'co.je', 'co.kr', 'co.lc', 'co.mg', 'co.ms', 'co.mu', 'co.nl', 'co.nz', 'co.uk', 'co.ve', 'co.za', 'com.af', 'com.ag', 'com.am', 'com.ar', 'com.au', 'com.br', 'com.bz', 'com.cm', 'com.cn', 'com.co', 'com.de', 'com.ec', 'com.es', 'com.gl', 'com.gr', 'com.gy', 'com.hn', 'com.ht', 'com.im', 'com.ki', 'com.lc', 'com.lv', 'com.mg', 'com.ms', 'com.mu', 'com.mx', 'com.nf', 'com.pe', 'com.ph', 'com.pk', 'com.pl', 'com.ps', 'com.pt', 'com.ro', 'com.ru', 'com.sb', 'com.sc', 'com.se', 'com.sg', 'com.so', 'com.tw', 'com.vc', 'com.ve', 'cpa.pro', 'cq.cn', 'daegu.kr', 'daejeon.kr', 'de.com', 'ebiz.tw', 'edu.cn', 'edu.gl', 'eng.pro', 'es.kr', 'eu.com', 'fin.ec', 'firm.in', 'fj.cn', 'game.tw', 'gangwon.kr', 'gb.com', 'gb.net', 'gd.cn', 'gen.in', 'go.kr', 'gov.cn', 'gr.com', 'gs.cn', 'gwangju.kr', 'gx.cn', 'gyeongbuk.kr', 'gyeonggi.kr', 'gyeongnam.kr', 'gz.cn', 'ha.cn', 'hb.cn', 'he.cn', 'hi.cn', 'hk.cn', 'hl.cn', 'hn.cn', 'hs.kr', 'hu.com', 'hu.net', 'idv.tw', 'in.net', 'incheon.kr', 'ind.in', 'info.ec', 'info.ht', 'info.ki', 'info.nf', 'info.pl', 'info.ve', 'jeju.kr', 'jeonbuk.kr', 'jeonnam.kr', 'jl.cn', 'jp.net', 'jpn.com', 'js.cn', 'jur.pro', 'jx.cn', 'kg.kr', 'kiwi.nz', 'kr.com', 'law.pro', 'ln.cn', 'me.uk', 'med.ec', 'med.pro', 'mex.com', 'mo.cn', 'ms.kr', 'ne.kr', 'net.af', 'net.ag', 'net.am', 'net.br', 'net.bz', 'net.cm', 'net.cn', 'net.co', 'net.ec', 'net.gg', 'net.gl', 'net.gr', 'net.gy', 'net.hn', 'net.ht', 'net.im', 'net.in', 'net.je', 'net.ki', 'net.lc', 'net.lv', 'net.mg', 'net.mu', 'net.my', 'net.nf', 'net.nz', 'net.ph', 'net.pk', 'net.pl', 'net.ps', 'net.ru', 'net.sb', 'net.sc', 'net.so', 'net.vc', 'net.ve', 'nm.cn', 'no.com', 'nom.ag', 'nom.co', 'nom.es', 'nom.ro', 'nx.cn', 'or.at', 'or.jp', 'or.kr', 'or.mu', 'org.af', 'org.ag', 'org.am', 'org.bz', 'org.cn', 'org.es', 'org.gg', 'org.gl', 'org.gr', 'org.hn', 'org.ht', 'org.il', 'org.im', 'org.in', 'org.je', 'org.ki', 'org.lc', 'org.lv', 'org.mg', 'org.ms', 'org.mu', 'org.my', 'org.nz', 'org.pk', 'org.pl', 'org.ps', 'org.ro', 'org.ru', 'org.sb', 'org.sc', 'org.so', 'org.uk', 'org.vc', 'org.ve', 'pe.kr', 'pro.ec', 'qc.com', 'qh.cn', 'radio.am', 'radio.fm', 're.kr', 'recht.pro', 'ru.com', 'sa.com', 'sc.cn', 'sc.kr', 'sd.cn', 'se.com', 'senet', 'seoul.kr', 'sh.cn', 'sn.cn', 'sx.cn', 'tj.cn', 'tw.cn', 'uk.com', 'uk.net', 'ulsan.kr', 'us.com', 'us.org', 'uy.com', 'web.ve', 'xj.cn', 'xz.cn', 'yn.cn', 'za.com', 'zj.cn');
$url_arr = explode(".", $url);
if (count($url_arr) <= 2) {
$host = $url;
} else {
$last = array_pop($url_arr);
$last_1 = array_pop($url_arr);
$last_2 = array_pop($url_arr);
$host = $last_1 . '.' . $last;
if (in_array($host, $dual_host)) {
$host = $last_2 . '.' . $last_1 . '.' . $last;
}
}
return $host;
}
function random_code_type($length = 8, $type = 'alpha-number')
{
$code_arr = array(
'alpha' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 'number' => '0123456789', 'sign' => '#$%@*-_',);
$type_arr = explode('-', $type);
foreach ($type_arr as $t) {
if (!array_key_exists($t, $code_arr)) {
trigger_error("Can not generate type ($t) code");
}
}
$chars = '';
foreach ($type_arr as $t) {
$chars .= $code_arr[$t];
}
$chars = str_shuffle($chars);
$number = $length > strlen($chars) - 1 ? strlen($chars) - 1 : $length;
return substr($chars, 0, $number);
}
function get_sub_data($pid, &$subData, &$data)
{
$param = [];
if (is_array($pid)) {
$param['in'] = $pid; //上级pid IN 查询
} else {
$param['eq'] = $pid; //上级 pid = 查询
}
//根据父节点,查找下级的子节点
$subList = search_all($param, $data);
if (empty($subList)) {
return $subData;
}
$tempSubIds = array_column($subList, 'id'); //获取这个节点的所有下级id
$subData = array_merge($subData, $subList); //用户下级数据合并
get_sub_data($tempSubIds, $subData, $data);
}
function get_sub_ids($pid, &$subIds, &$data)
{
$param = [];
if (is_array($pid)) {
$param['in'] = $pid; //上级pid IN 查询
} else {
$param['eq'] = $pid; //上级 pid = 查询
}
//根据父节点,查找下级的子节点
$subList = search_all($param, $data);
if (empty($subList)) {
return $subIds;
}
$tempSubIds = array_column($subList, 'id'); //获取这个节点的所有下级id
$subIds = array_merge($subIds, $tempSubIds); //用户下级ID合并
get_sub_ids($tempSubIds, $subIds, $data);
}
//模拟数据表查询所有操作
function search_all($param, &$data)
{
$result = [];
if (array_key_exists('eq', $param)) { //等于操作
$searchValue = $param['eq'];
foreach ($data as $value) {
if ($searchValue == $value['parent_id']) {
$result[] = $value;
}
}
}
if (array_key_exists('in', $param)) { //in查询
$searchArray = $param['in'];
foreach ($data as $value) {
if (in_array($value['parent_id'], $searchArray)) {
$result[] = $value;
}
}
}
return $result;
}
function createFile($file)
{
//循环遍历文件夹,循环条件文件夹不存在
if (is_dir($file)) {
return;
}
//强制将'\'转换成 '/'
$file = str_replace('\\', '/', $file);
$file = substr($file, 0, strrpos($file, '/'));
//创建文件夹,若创建失败错误提示被抑制
@mkdir($file);
//获取上级文件夹路径地址
$file = substr($file, 0, strrpos($file, '/'));
// echo 'sss';
//打印路径
//echo $file . '';
//调用自身方法,将上级目录路径传入
createFile($file);
}
function mkdirs($dir, $mode = 0777) {
if (! is_dir ( $dir )) {
if (! mkdirs ( dirname ( $dir ) )) {
return false;
}
if (! mkdir ( $dir, $mode )) {
return false;
}
}
return true;
}
if(!function_exists("createUserToken")){
/**
* @throws TokenException
*/
function createUserToken($data, $jtiType='admin')
{
try{
$jwtConfig = config("jwt")['stores']['token'];
$jti = $jtiType.'_'.mt_rand(1000,9999).$data['uid'];
$jwtObject = Jwt::getInstance()->setSecretKey($jwtConfig['signer_key'])->publish();
$jwtObject->setAlg('HMACSHA256');
$jwtObject->setExp(time()+$jwtConfig['refresh_ttL']); //过期时间
$jwtObject->setIat(time()); // 发布时间
$jwtObject->setIss('huocms'); // 发行人
$jwtObject->setJti(md5($jti)); // jwt id 用于标识该jwt
$jwtObject->setNbf(time()); // 在此之前不可用
$jwtObject->setSub($jtiType); // 主题
$jwtObject->setData($data);
return $jwtObject->__toString();
}catch (Exception $e){
throw new TokenException("登录失败",-402);
}
}
}