CRMEB/crmeb/app/common.php
2022-02-16 17:11:48 +08:00

908 lines
27 KiB
PHP
Raw 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
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
// 应用公共文件
use think\exception\ValidateException;
use crmeb\services\FormBuilder as Form;
use crmeb\services\UploadService;
if (!function_exists('getWorkerManUrl')) {
/**
* 获取客服数据
* @return mixed
*/
function getWorkerManUrl()
{
$ws = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'wss://' : 'ws://';
$host = $_SERVER['HTTP_HOST'];
$data['admin'] = $ws . $host . '/notice';
$data['chat'] = $ws . $host . '/msg';
return $data;
}
}
if (!function_exists('object2array')) {
/**
* 对象转数组
* @return mixed
*/
function object2array($object)
{
if (is_object($object)) {
foreach ($object as $key => $value) {
$array[$key] = $value;
}
} else {
$array = $object;
}
return $array;
}
}
if (!function_exists('exception')) {
/**
* 抛出异常处理
*
* @param string $msg 异常消息
* @param integer $code 异常代码 默认为0
* @param string $exception 异常类
*
* @throws Exception
*/
function exception($msg, $code = 0, $exception = '')
{
$e = $exception ?: '\think\Exception';
throw new $e($msg, $code);
}
}
if (!function_exists('sys_config')) {
/**
* 获取系统单个配置
* @param string $name
* @param string $default
* @return string
*/
function sys_config(string $name, $default = '')
{
if (empty($name))
return $default;
$sysConfig = app('sysConfig')->get($name);
if (is_array($sysConfig)) {
foreach ($sysConfig as &$item) {
if (strpos($item, '/uploads/system/') !== false) $item = set_file_url($item);
}
} else {
if (strpos($sysConfig, '/uploads/system/') !== false) $sysConfig = set_file_url($sysConfig);
}
$config = is_array($sysConfig) ? $sysConfig : trim($sysConfig);
if ($config === '' || $config == false) {
return $default;
} else {
return $config;
}
}
}
if (!function_exists('sys_data')) {
/**
* 获取系统单个配置
* @param string $name
* @return string
*/
function sys_data(string $name, int $limit = 0)
{
return app('sysGroupData')->getData($name, $limit);
}
}
if (!function_exists('filter_emoji')) {
// 过滤掉emoji表情
function filter_emoji($str)
{
$str = preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换
'/./u',
function (array $match) {
return strlen($match[0]) >= 4 ? '' : $match[0];
},
$str);
return $str;
}
}
if (!function_exists('str_middle_replace')) {
/** TODO 系统未使用
* @param string $string 需要替换的字符串
* @param int $start 开始的保留几位
* @param int $end 最后保留几位
* @return string
*/
function str_middle_replace($string, $start, $end)
{
$strlen = mb_strlen($string, 'UTF-8');//获取字符串长度
$firstStr = mb_substr($string, 0, $start, 'UTF-8');//获取第一位
$lastStr = mb_substr($string, -1, $end, 'UTF-8');//获取最后一位
return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($string, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr;
}
}
if (!function_exists('sensitive_words_filter')) {
/**
* 敏感词过滤
*
* @param string
* @return string
*/
function sensitive_words_filter($str)
{
if (!$str) return '';
$file = app()->getAppPath() . 'public/statics/plug/censorwords/CensorWords';
$words = file($file);
foreach ($words as $word) {
$word = str_replace(array("\r\n", "\r", "\n", "/", "<", ">", "=", " "), '', $word);
if (!$word) continue;
$ret = preg_match("/$word/", $str, $match);
if ($ret) {
return $match[0];
}
}
return '';
}
}
if (!function_exists('make_path')) {
/**
* 上传路径转化,默认路径
* @param $path
* @param int $type
* @param bool $force
* @return string
*/
function make_path($path, int $type = 2, bool $force = false)
{
$path = DS . ltrim(rtrim($path));
switch ($type) {
case 1:
$path .= DS . date('Y');
break;
case 2:
$path .= DS . date('Y') . DS . date('m');
break;
case 3:
$path .= DS . date('Y') . DS . date('m') . DS . date('d');
break;
}
try {
if (is_dir(app()->getRootPath() . 'public' . DS . 'uploads' . $path) == true || mkdir(app()->getRootPath() . 'public' . DS . 'uploads' . $path, 0777, true) == true) {
return trim(str_replace(DS, '/', $path), '.');
} else return '';
} catch (\Exception $e) {
if ($force)
throw new \Exception($e->getMessage());
return '无法创建文件夹,请检查您的上传目录权限:' . app()->getRootPath() . 'public' . DS . 'uploads' . DS . 'attach' . DS;
}
}
}
if (!function_exists('curl_file_exist')) {
/**
* CURL 检测远程文件是否在
* @param $url
* @return bool
*/
function curl_file_exist($url)
{
$ch = curl_init();
try {
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$contents = curl_exec($ch);
if (preg_match("/404/", $contents)) return false;
if (preg_match("/403/", $contents)) return false;
return true;
} catch (\Exception $e) {
return false;
}
}
}
if (!function_exists('set_file_url')) {
/**
* 设置附加路径
* @param $url
* @return bool
*/
function set_file_url($image, $siteUrl = '')
{
if (!strlen(trim($siteUrl))) $siteUrl = sys_config('site_url');
if (!$image) return $image;
if (is_array($image)) {
foreach ($image as &$item) {
$domainTop1 = substr($item, 0, 4);
$domainTop2 = substr($item, 0, 2);
if ($domainTop1 != 'http' && $domainTop2 != '//')
$item = $siteUrl . str_replace('\\', '/', $item);
}
} else {
$domainTop1 = substr($image, 0, 4);
$domainTop2 = substr($image, 0, 2);
if ($domainTop1 != 'http' && $domainTop2 != '//')
$image = $siteUrl . str_replace('\\', '/', $image);
}
return $image;
}
}
if (!function_exists('set_http_type')) {
/**
* 修改 https 和 http
* @param $url $url 域名
* @param int $type 0 返回https 1 返回 http
* @return string
*/
function set_http_type($url, $type = 0)
{
$domainTop = substr($url, 0, 5);
if ($type) {
if ($domainTop == 'https') $url = 'http' . substr($url, 5, strlen($url));
} else {
if ($domainTop != 'https') $url = 'https:' . substr($url, 5, strlen($url));
}
return $url;
}
}
if (!function_exists('check_card')) {
/**
* 身份证验证
* @param $card
* @return bool
*/
function check_card($card)
{
$city = [11 => "北京", 12 => "天津", 13 => "河北", 14 => "山西", 15 => "内蒙古", 21 => "辽宁", 22 => "吉林", 23 => "黑龙江 ", 31 => "上海", 32 => "江苏", 33 => "浙江", 34 => "安徽", 35 => "福建", 36 => "江西", 37 => "山东", 41 => "河南", 42 => "湖北 ", 43 => "湖南", 44 => "广东", 45 => "广西", 46 => "海南", 50 => "重庆", 51 => "四川", 52 => "贵州", 53 => "云南", 54 => "西藏 ", 61 => "陕西", 62 => "甘肃", 63 => "青海", 64 => "宁夏", 65 => "新疆", 71 => "台湾", 81 => "香港", 82 => "澳门", 91 => "国外 "];
$tip = "";
$match = "/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/";
$pass = true;
if (!$card || !preg_match($match, $card)) {
//身份证格式错误
$pass = false;
} else if (!$city[substr($card, 0, 2)]) {
//地址错误
$pass = false;
} else {
//18位身份证需要验证最后一位校验位
if (strlen($card) == 18) {
$card = str_split($card);
//∑(ai×Wi)(mod 11)
//加权因子
$factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
//校验位
$parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
$sum = 0;
$ai = 0;
$wi = 0;
for ($i = 0; $i < 17; $i++) {
$ai = $card[$i];
$wi = $factor[$i];
$sum += $ai * $wi;
}
$last = $parity[$sum % 11];
if ($parity[$sum % 11] != $card[17]) {
// $tip = "校验位错误";
$pass = false;
}
} else {
$pass = false;
}
}
if (!$pass) return false;/* 身份证格式错误*/
return true;/* 身份证格式正确*/
}
}
if (!function_exists('check_link')) {
/**
* 地址验证
* @param string $link
* @return false|int
*/
function check_link(string $link)
{
return preg_match("/^(http|https|ftp):\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+[\/=\?%\-&_~`@[\]\:+!]*([^<>\”])*$/", $link);
}
}
if (!function_exists('check_phone')) {
/**
* 手机号验证
* @param $phone
* @return false|int
*/
function check_phone($phone)
{
return preg_match("/^1[3456789]\d{9}$/", $phone);
}
}
if (!function_exists('anonymity')) {
/**
* 匿名处理处理用户昵称
* @param $name
* @return string
*/
function anonymity($name, $type = 1)
{
if ($type == 1) {
return mb_substr($name, 0, 1, 'UTF-8') . '**' . mb_substr($name, -1, 1, 'UTF-8');
} else {
$strLen = mb_strlen($name, 'UTF-8');
$min = 3;
if ($strLen <= 1)
return '*';
if ($strLen <= $min)
return mb_substr($name, 0, 1, 'UTF-8') . str_repeat('*', $min - 1);
else
return mb_substr($name, 0, 1, 'UTF-8') . str_repeat('*', $strLen - 1) . mb_substr($name, -1, 1, 'UTF-8');
}
}
}
if (!function_exists('sort_list_tier')) {
/**
* 分级排序
* @param $data
* @param int $pid
* @param string $field
* @param string $pk
* @param string $html
* @param int $level
* @param bool $clear
* @return array
*/
function sort_list_tier($data, $pid = 0, $field = 'pid', $pk = 'id', $html = '|-----', $level = 1, $clear = true)
{
static $list = [];
if ($clear) $list = [];
foreach ($data as $k => $res) {
if ($res[$field] == $pid) {
$res['html'] = str_repeat($html, $level);
$list[] = $res;
unset($data[$k]);
sort_list_tier($data, $res[$pk], $field, $pk, $html, $level + 1, false);
}
}
return $list;
}
}
if (!function_exists('sort_city_tier')) {
/**
* 城市数据整理
* @param $data
* @param int $pid
* @param string $field
* @param string $pk
* @param string $html
* @param int $level
* @param bool $clear
* @return array
*/
function sort_city_tier($data, $pid = 0, $navList = [])
{
foreach ($data as $k => $menu) {
if ($menu['parent_id'] == $pid) {
unset($menu['parent_id']);
unset($data[$k]);
$menu['c'] = sort_city_tier($data, $menu['v']);
$navList[] = $menu;
}
}
return $navList;
}
}
if (!function_exists('time_tran')) {
/**
* 时间戳人性化转化
* @param $time
* @return string
*/
function time_tran($time)
{
$t = time() - $time;
$f = array(
'31536000' => '年',
'2592000' => '个月',
'604800' => '星期',
'86400' => '天',
'3600' => '小时',
'60' => '分钟',
'1' => '秒'
);
foreach ($f as $k => $v) {
if (0 != $c = floor($t / (int)$k)) {
return $c . $v . '前';
}
}
}
}
if (!function_exists('url_to_path')) {
/**
* url转换路径
* @param $url
* @return string
*/
function url_to_path($url)
{
$path = trim(str_replace('/', DS, $url), DS);
if (0 !== strripos($path, 'public'))
$path = 'public' . DS . $path;
return app()->getRootPath() . $path;
}
}
if (!function_exists('path_to_url')) {
/**
* 路径转url路径
* @param $path
* @return string
*/
function path_to_url($path)
{
return trim(str_replace(DS, '/', $path), '.');
}
}
if (!function_exists('image_to_base64')) {
/**
* 获取图片转为base64
* @param string $avatar
* @return bool|string
*/
function image_to_base64($avatar = '', $timeout = 9)
{
$avatar = str_replace('https', 'http', $avatar);
try {
$url = parse_url($avatar);
$url = $url['host'];
$header = [
'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefox/45.0',
'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding: gzip, deflate, br',
'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Host:' . $url
];
$dir = pathinfo($url);
$host = $dir['dirname'];
$refer = $host . '/';
$curl = curl_init();
curl_setopt($curl, CURLOPT_REFERER, $refer);
curl_setopt($curl, CURLOPT_URL, $avatar);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
$data = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($code == 200) {
return "data:image/jpeg;base64," . base64_encode($data);
} else {
return false;
}
} catch (\Exception $e) {
return false;
}
}
}
if (!function_exists('put_image')) {
/**
* 获取图片转为base64
* @param string $avatar
* @return bool|string
*/
function put_image($url, $filename = '')
{
if ($url == '') {
return false;
}
try {
if ($filename == '') {
$ext = pathinfo($url);
if ($ext['extension'] != "jpg" && $ext['extension'] != "png" && $ext['extension'] != "jpeg") {
return false;
}
$filename = time() . "." . $ext['extension'];
}
//文件保存路径
ob_start();
readfile($url);
$img = ob_get_contents();
ob_end_clean();
$path = 'uploads/qrcode';
$fp2 = fopen($path . '/' . $filename, 'a');
fwrite($fp2, $img);
fclose($fp2);
return $path . '/' . $filename;
} catch (\Exception $e) {
return false;
}
}
}
if (!function_exists('debug_file')) {
/**
* 文件调试
* @param $content
*/
function debug_file($content, string $fileName = 'error', string $ext = 'txt')
{
$msg = '[' . date('Y-m-d H:i:s', time()) . '] [ DEBUG ] ';
$pach = app()->getRuntimePath();
file_put_contents($pach . $fileName . '.' . $ext, $msg . print_r($content, true) . "\r\n", FILE_APPEND);
}
}
if (!function_exists('sql_filter')) {
/**
* sql 参数过滤
* @param string $str
* @return mixed
*/
function sql_filter(string $str)
{
$filter = ['select ', 'insert ', 'update ', 'delete ', 'drop', 'truncate ', 'declare', 'xp_cmdshell', '/add', ' or ', 'exec', 'create', 'chr', 'mid', ' and ', 'execute'];
$toupper = array_map(function ($str) {
return strtoupper($str);
}, $filter);
return str_replace(array_merge($filter, $toupper, ['%20']), '', $str);
}
}
if (!function_exists('is_brokerage_statu')) {
/**
* 是否能成为推广人
* @param float $price
* @return bool
*/
function is_brokerage_statu(float $price)
{
if (!sys_config('brokerage_func_status')) {
return false;
}
$storeBrokerageStatus = sys_config('store_brokerage_statu', 1);
if ($storeBrokerageStatus == 1) {
return false;
} else if ($storeBrokerageStatus == 2) {
return false;
} else {
$storeBrokeragePrice = sys_config('store_brokerage_price', 0);
return $price >= $storeBrokeragePrice;
}
}
}
if (!function_exists('array_unique_fb')) {
/**
* 二维数组去掉重复值
* @param $array
* @return array
*/
function array_unique_fb($array)
{
$out = array();
foreach ($array as $key => $value) {
if (!in_array($value, $out)) {
$out[$key] = $value;
}
}
$out = array_values($out);
return $out;
}
}
if (!function_exists('get_crmeb_version')) {
/**
* 获取CRMEB系统版本号
* @param string $default
* @return string
*/
function get_crmeb_version($default = 'v1.0.0')
{
try {
$version = parse_ini_file(app()->getRootPath() . '.version');
return $version['version'] ?? $default;
} catch (\Throwable $e) {
return $default;
}
}
}
if (!function_exists('get_file_link')) {
/**
* 获取文件带域名的完整路径
* @param string $link
* @return string
*/
function get_file_link(string $link)
{
if (!$link) {
return '';
}
if (strstr('http', $link) === false) {
return app()->request->domain() . $link;
} else {
return $link;
}
}
}
if (!function_exists('tidy_tree')) {
/**
* 格式化分类
* @param $menusList
* @param int $pid
* @param array $navList
* @return array
*/
function tidy_tree($menusList, $pid = 0, $navList = [])
{
foreach ($menusList as $k => $menu) {
if ($menu['parent_id'] == $pid) {
unset($menusList[$k]);
$menu['children'] = tidy_tree($menusList, $menu['id']);
if ($menu['children']) $menu['expand'] = true;
$navList[] = $menu;
}
}
return $navList;
}
}
if (!function_exists('create_form')) {
/**
* 表单生成方法
* @param string $title
* @param array $field
* @param $url
* @param string $method
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
function create_form(string $title, array $field, $url, string $method = 'POST')
{
$form = Form::createForm((string)$url);//提交地址
$form->setMethod($method);//提交方式
$form->setRule($field);//表单字段
$form->setTitle($title);//表单标题
$rules = $form->formRule();
$title = $form->getTitle();
$action = $form->getAction();
$method = $form->getMethod();
$info = '';
$status = true;
$methodData = ['POST', 'PUT', 'GET', 'DELETE'];
if (!in_array(strtoupper($method), $methodData)) {
throw new ValidateException('请求方式有误');
}
return compact('rules', 'title', 'action', 'method', 'info', 'status');
}
}
if (!function_exists('msectime')) {
/**
* 获取毫秒数
* @return float
*/
function msectime()
{
list($msec, $sec) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
}
}
if (!function_exists('array_bc_sum')) {
/**
* 获取一维数组的总合高精度
* @param array $data
* @return string
*/
function array_bc_sum(array $data)
{
$sum = '0';
foreach ($data as $item) {
$sum = bcadd($sum, (string)$item, 2);
}
return $sum;
}
}
if (!function_exists('get_tree_children')) {
/**
* tree 子菜单
* @param array $data 数据
* @param string $childrenname 子数据名
* @param string $keyName 数据key名
* @param string $pidName 数据上级key名
* @return array
*/
function get_tree_children(array $data, string $childrenname = 'children', string $keyName = 'id', string $pidName = 'pid')
{
$list = array();
foreach ($data as $value) {
$list[$value[$keyName]] = $value;
}
static $tree = array(); //格式化好的树
foreach ($list as $item) {
if (isset($list[$item[$pidName]])) {
$list[$item[$pidName]][$childrenname][] = &$list[$item[$keyName]];
} else {
$tree[] = &$list[$item[$keyName]];
}
}
return $tree;
}
}
if (!function_exists('get_tree_children_value')) {
function get_tree_children_value(array $data, $value, string $childrenname = 'children', string $keyName = 'id')
{
static $childrenValue = [];
foreach ($data as $item) {
$childrenData = $item[$childrenname] ?? [];
if (count($childrenData)) {
return get_tree_children_value($childrenData, $childrenname, $keyName);
} else {
if ($item[$keyName] == $value) {
$childrenValue[] = $item['value'];
}
}
}
return $childrenValue;
}
}
if (!function_exists('get_tree_value')) {
/**
* 获取
* @param array $data
* @param int|string $value
* @return array
*/
function get_tree_value(array $data, $value)
{
static $childrenValue = [];
foreach ($data as &$item) {
if ($item['value'] == $value) {
$childrenValue[] = $item['value'];
if ($item['pid']) {
$value = $item['pid'];
unset($item);
return get_tree_value($data, $value);
}
}
}
return $childrenValue;
}
}
if (!function_exists('get_image_thumb')) {
/**
* 获取缩略图
* @param $filePath
* @param string $type all|big|mid|small
* @param bool $is_remote_down
* @return mixed|string|string[]
*/
function get_image_thumb($filePath, string $type = 'all', bool $is_remote_down = false)
{
if (!$filePath || !is_string($filePath) || strpos($filePath, '?') !== false) return $filePath;
try {
$upload = UploadService::getOssInit($filePath, $is_remote_down);
$fileArr = explode('/', $filePath);
$data = $upload->thumb($filePath, end($fileArr), $type);
$image = $type == 'all' ? $data : $data[$type] ?? $filePath;
} catch (\Throwable $e) {
$image = $filePath;
\think\facade\Log::error('获取缩略图失败,原因:' . $e->getMessage() . '----' . $e->getFile() . '----' . $e->getLine() . '----' . $filePath);
}
$data = parse_url($image);
if (!isset($data['host']) && (substr($image, 0, 2) == './' || substr($image, 0, 1) == '/')) {//不是完整地址
$image = sys_config('site_url') . $image;
}
//请求是https 图片是http 需要改变图片地址
if (strpos(request()->domain(), 'https:') !== false && strpos($image, 'https:') === false) {
$image = str_replace('http:', 'https:', $image);
}
return $image;
}
}
if (!function_exists('get_thumb_water')) {
/**
* 处理数组获取缩略图、水印
* @param $list
* @param string $type
* @param array|string[] $field 1、['image','images'] type 取值参数:type 2、['small'=>'image','mid'=>'images'] type 取field数组的key
* @param bool $is_remote_down
* @return array|mixed|string|string[]
*/
function get_thumb_water($list, string $type = 'small', array $field = ['image'], bool $is_remote_down = false)
{
if (!$list || !$field) return $list;
$baseType = $type;
$data = $list;
if (is_string($list)) {
$field = [$type => 'image'];
$data = ['image' => $list];
}
if (is_array($data)) {
foreach ($field as $type => $key) {
if (is_integer($type)) {//索引数组默认type
$type = $baseType;
}
//一维数组
if (isset($data[$key])) {
if (is_array($data[$key])) {
$path_data = [];
foreach ($data[$key] as $k => $path) {
$path_data[] = get_image_thumb($path, $type, $is_remote_down);
}
$data[$key] = $path_data;
} else {
$data[$key] = get_image_thumb($data[$key], $type, $is_remote_down);
}
} else {
foreach ($data as &$item) {
if (!isset($item[$key]))
continue;
if (is_array($item[$key])) {
$path_data = [];
foreach ($item[$key] as $k => $path) {
$path_data[] = get_image_thumb($path, $type, $is_remote_down);
}
$item[$key] = $path_data;
} else {
$item[$key] = get_image_thumb($item[$key], $type, $is_remote_down);
}
}
}
}
}
return is_string($list) ? ($data['image'] ?? '') : $data;
}
}