<?php // +---------------------------------------------------------------------- // | Bwsaas // +---------------------------------------------------------------------- // | Copyright (c) 2015~2020 http://www.buwangyun.com All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Gitee ( https://gitee.com/buwangyun/bwsaas ) // +---------------------------------------------------------------------- // | Author: buwangyun <hnlg666@163.com> // +---------------------------------------------------------------------- // | Date: 2020-9-28 10:55:00 // +---------------------------------------------------------------------- use think\facade\Event; // 应用公共函数文件 if (!function_exists('set_addons_info')) { /** * 设置基础配置信息. * * @param string $name 插件名 * @param array $array 配置数据 * * @return bool * @throws Exception */ function set_addons_info($name, $array) { $file = ADDON_PATH . $name . DS . 'info.ini'; $addon = get_addons_instance($name); $array = $addon->setInfo($name, $array); if (!isset($array['name']) || !isset($array['title']) || !isset($array['version'])) { throw new Exception('插件配置写入失败'); } $res = []; foreach ($array as $key => $val) { if (is_array($val)) { $res[] = "[$key]"; foreach ($val as $skey => $sval) { $res[] = "$skey = " . (is_numeric($sval) ? $sval : $sval); } } else { $res[] = "$key = " . (is_numeric($val) ? $val : $val); } } if ($handle = fopen($file, 'w')) { fwrite($handle, implode("\n", $res) . "\n"); fclose($handle); //清空当前配置缓存 \think\facade\Config::set([$name => null], 'addoninfo'); } else { throw new Exception('文件没有写入权限'); } return true; } } if (!function_exists('set_addons_config')) { /** * 写入配置文件. * * @param string $name 插件名 * @param array $config 配置数据 * @param bool $writefile 是否写入配置文件 * * @return bool * @throws Exception */ function set_addons_config($name, $config, $writefile = true) { $addon = get_addons_instance($name); $addon->setConfig($name, $config); $fullconfig = get_addons_config($name, true); foreach ($fullconfig as $k => &$v) { if (isset($config[$v['name']])) { $value = $v['type'] !== 'array' && is_array($config[$v['name']]) ? implode(',', $config[$v['name']]) : $config[$v['name']]; $v['value'] = $value; } } if ($writefile) { // 写入配置文件 set_addons_fullconfig($name, $fullconfig); } return true; } } if (!function_exists('set_addons_fullconfig')) { /** * 写入配置文件. * * @param string $name 插件名 * @param array $array 配置数据 * * @return bool * @throws Exception */ function set_addons_fullconfig($name, $array) { $file = ADDON_PATH . $name . DS . 'config.php'; if (!\buwang\util\File::is_really_writable($file)) { throw new Exception('文件没有写入权限'); } if ($handle = fopen($file, 'w')) { fwrite($handle, "<?php\n\n" . 'return ' . var_export($array, true) . ";\n"); fclose($handle); } else { throw new Exception('文件没有写入权限'); } return true; } } if (!function_exists('get_sql_array')) { /** * * 读取sql文件为数组 * * @param $sqlFile sql 文件路径 * * @param string $prefix 添加表前缀 * * @return array|bool * */ function get_sql_array($sqlFile) { $sql = file_get_contents($sqlFile); $str = preg_replace('/(--.*)|(\/\*(.|\s)*?\*\/)|(\n)/', '', $sql); $list = explode(';', trim($str)); foreach ($list as $key => $val) { if (empty($val)) { unset($list[$key]); } else { $list[$key] .= ';'; } } return array_values($list); } } if (!function_exists('bw_config')) { /** * @param string $name 配置名 * @param null $default 配置默认值 * @param null $member_id 租户id * @param null $dir 应用标识 * @return array|mixed|null */ function bw_config(string $name, $default = null, $member_id = null, $dir = null) { return app\manage\model\Config::memberAndAdminConfig($name, $default, $member_id, $dir); } } if (!function_exists('en_code')) { /** * 针对于ID的可逆加密函数,也可以用作于邀请码之类 * @param int $code */ function en_code($code) { static $source_string = 'E5FCDG3HQA4B1NOPIJ2RSTUV67MWX89KLYZ'; $num = $code; $code = ''; while ($num > 0) { $mod = $num % 35; $num = ($num - $mod) / 35; $code = $source_string[$mod] . $code; } if (empty($code[3])) { $code = str_pad($code, 4, '0', STR_PAD_LEFT); } return $code; } } if (!function_exists('de_code')) { /** * 针对于ID的可逆加密函数,也可以用作于邀请码之类 * @param string $code */ function de_code($code) { static $source_string = 'E5FCDG3HQA4B1NOPIJ2RSTUV67MWX89KLYZ'; if (strrpos($code, '0') !== false) { $code = substr($code, strrpos($code, '0') + 1); } $len = strlen($code); $code = strrev($code); $num = 0; for ($i = 0; $i < $len; $i++) { $num += strpos($source_string, $code[$i]) * pow(35, $i); } return $num; } } if (!function_exists('en_mobile')) { /** * 隐藏手机号中间四位,从第三个字符隐藏4个字符 * @param $phone * @param int $s * @param int $d * @return string|string[] */ function en_mobile($phone, $s = 3, $d = 4) { return substr_replace($phone, '****', $s, $d); } } if (!function_exists('get_num_code')) { /** * 生成随机数 * @param int $limit * @return string */ function get_num_code($limit = 6) { $rand_array = range(0, 9); shuffle($rand_array); //调用现成的数组随机排列函数 $str = array_slice($rand_array, 0, $limit);//截取前$limit个 return implode(null, $str); } } if (!function_exists('bw_img_url')) { /** * 设置附加路径 * @param $image * @param string $siteUrl * @return bool */ function bw_img_url($image, $siteUrl = '') { if (!strlen(trim($siteUrl))) $siteUrl = bw_config('web_url'); //var_dump($siteUrl);die; $domainTop = substr($image, 0, 4); if ($domainTop == 'http') return $image; $image = str_replace('\\', '/', $image); //var_dump(bw_config('web_url'));die; return $siteUrl . $image; } } if (!function_exists('anonymity')) { /** * 匿名处理处理用户昵称 * @param $name * @return string */ function anonymity($name) { $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('bw_data')) { /** 返回组合数据对象 * @param int|array|string $groupName 选填 传数字或字符串标识则查该项组合数据 传数组则 格式为:[ '数据组ID或字符串标识','租户ID','应用标识'] 表示只查某个租户(租户ID=0 为总后台) * @param int|boolean|string $id 选填 传数字则只查单条组合数据 传false则返回组合数据对象,自己写查询条件。 * @param int|null $member_id 选填 传0 则只查总后台组合数据 传租户id则查某个租户的组合数据,默认为null表示从登录信息自动取租户id,取不到就查总后台数据 */ function bw_data($groupName = '', $id = 0, $where = ['status' => 1], $page = null, $limit = null, $sort = 'sort desc,id desc') { return app\manage\model\ConfigGroupData::getDataList($groupName, $id, $where, $page, $limit, $sort); } } if (!function_exists('bw_value_data')) { /** 取配置数据组数据(引用传递方法,根据情况可以不用取返回值) 返回false则说明有错误 调用bw_value_data_errormsg()方法可获取错误信息 * @param string $where 如果传入的是数据列表或单个数据对象则不需要接收返回结果,如果方法不返回falsee则说明引用对象值已经改变,如果传入的是id,则需要接收返回结果或将id参数当做结果 * @param ConfigGroup $ConfigGroup 数据组对象,可不传,不传的话方法内多查一次数据库 * @return ConfigGroupData|array|int|mixed|string|boolean */ function bw_value_data(&$where, $ConfigGroup = null) { return app\manage\model\ConfigGroupData::getValueData($where, $ConfigGroup); } } if (!function_exists('bw_value_data_errormsg')) { /** 调用bw_value_data()方法返回false时,调用该方法取错误信息 */ function bw_value_data_errormsg($defaultMsg = '操作失败,请稍候再试!') { return app\manage\model\ConfigGroupData::getError($defaultMsg); } } if (!function_exists('get_session_id')) { /** 调用bw_value_data()方法返回false时,调用该方法取错误信息 */ function get_session_id() { return \think\facade\Session::getId(); } } 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('sysuri')) { /** * 生成最短URL地址 * @param string $url 路由地址 * @param array $vars 变量 * @param boolean|string $suffix 后缀 * @param boolean|string $domain 域名 * @return string */ function sysuri($url = '', array $vars = [], $suffix = false, $domain = false) { return app('systemService')->sysuri($url, $vars, $suffix, $domain); } } if (!function_exists('get_month')) { /** * 格式化月份 * @param string $time * @param int $ceil * @return array */ function get_month($time = '', $ceil = 0) { if (empty($time)) { $firstday = date("Y-m-01", time()); $lastday = date("Y-m-d", strtotime("$firstday +1 month -1 day")); } else if ($time == 'n') { if ($ceil != 0) $season = ceil(date('n') / 3) - $ceil; else $season = ceil(date('n') / 3); $firstday = date('Y-m-01', mktime(0, 0, 0, ($season - 1) * 3 + 1, 1, date('Y'))); $lastday = date('Y-m-t', mktime(0, 0, 0, $season * 3, 1, date('Y'))); } else if ($time == 'y') { $firstday = date('Y-01-01'); $lastday = date('Y-12-31'); } else if ($time == 'h') { $firstday = date('Y-m-d', strtotime('this week +' . $ceil . ' day')) . ' 00:00:00'; $lastday = date('Y-m-d', strtotime('this week +' . ($ceil + 1) . ' day')) . ' 23:59:59'; } return array($firstday, $lastday); } } if (!function_exists('get_token')) { function get_token($request) { $token = $request->server('HTTP_TOKEN');//TODO:改变顺序 头 -- cookie -- session -- 参数 // && in_array($request->header('scopes'),['member','admin']) if ((!$token || $token == 'null')) $token = cookie('token'); //如果不存在,往session中取[此处取法暂时不用] //if (!$token || $token == 'null') $token = app('userService')->getLogin('token'); //如果不存在,往参数中取 if (!$token) $token = $request->request('token'); return $token ?: ''; } } //目录创建 if (!function_exists('is_mkdir')) { function is_mkdir($dir) { if (!is_dir($dir)) { // 创建目录并赋予权限 mkdir($dir, 0777, true); } } } //js鉴权 if (!function_exists('auth')) { function auth($url) { if ($url) return true; else return false; } } //重新排列数组的key 从0开始 if (!function_exists('reform_keys')) { function reform_keys($array) { if (!is_array($array)) { return $array; } $keys = implode('', array_keys($array)); if (is_numeric($keys)) { $array = array_values($array); } $array = array_map('reform_keys', $array); //框架中这么写, $array = array_map([$this,'reform_keys '],$array ); return $array; } ; } //获取用户组的scopes if (!function_exists('get_scopes')) { function get_scopes($request) { $scopes = $request->header('scopes'); if (!$scopes || !in_array($scopes, BW_CLIENT_TYPE)) { //模板解析时重定向至登录页面 /*-----------------------获取访问类的scopes Start--------------------------------------*/ list($module, $controller) = [app('http')->getName(), str_replace('.', '/', $request->controller())]; //通过反射获取当前php文件的实例 $ref_class = new \ReflectionClass(strtr("app/{$module}/controller/{$controller}", '/', '\\')); //通过方法名getScopes获取指定方法并执行 getScopes需是public属性,否则需要使用setAccessible(true)方法设置方法的可访问性 $scopes = $ref_class->getmethod('getScopes')->invoke($ref_class->newInstance(app())); } return $scopes; } ; } /** * 订单号 */ if (!function_exists('get_uuid')) { function get_uuid() { $osn = date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8); return $osn; } } /** * 多维数组去重 */ if (!function_exists('multipart_array_uni')) { function multipart_array_uni(&$my_array) { // 新建一个空的数组. $tmp_array = array(); $new_array = array(); // 1. 循环出所有的行. ( $val 就是某个行) foreach ($my_array as $k => $val) { $hash = md5(json_encode($val)); if (!in_array($hash, $tmp_array)) { // 2. 在 foreach 循环的主体中, 把每行数组对象得hash 都赋值到那个临时数组中. $tmp_array[] = $hash; $new_array[] = $val; } } $my_array = $new_array; return $new_array; } } 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('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; } } } /** * 无限极分类,根据父类id找所有子类 */ if (!function_exists('get_real_ip')) { function get_real_ip() { if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $cip = $_SERVER['HTTP_CLIENT_IP']; } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $cip = $_SERVER["HTTP_X_FORWARDED_FOR"]; } else if (!empty($_SERVER["REMOTE_ADDR"])) { $cip = $_SERVER["REMOTE_ADDR"]; } else { $cip = ''; } preg_match("/[\d\.]{7,15}/", $cip, $cips); $cip = isset($cips[0]) ? $cips[0] : 'unknown'; unset($cips); return $cip; } } if (!function_exists('get_login_member_id')) { /** 得到当前登录的顶级租户ID */ function get_login_member_id($memberId = 0) { $member_id_info = \buwang\util\Util::getLoginMemberId($memberId);//得到租户ID if (!$member_id_info) return $memberId; return $member_id_info['memberId'];//得到租户ID } } if (!function_exists('get_login_info')) { /** 得到当前登录信息 */ function get_login_info($memberId = 0) { return \buwang\util\Util::getLoginMemberId($memberId);//得到租户ID } } 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('encode_str')) { /** * 加密 UTF8 字符串 * @param string $content * @return string */ function encode_str($content) { list($chars, $length) = ['', strlen($string = iconv('UTF-8', 'GBK//TRANSLIT', $content))]; for ($i = 0; $i < $length; $i++) $chars .= str_pad(base_convert(ord($string[$i]), 10, 36), 2, 0, 0); return $chars; } } if (!function_exists('decode_str')) { /** * 解密 UTF8 字符串 * @param string $content * @return string */ function decode_str($content) { $chars = ''; foreach (str_split($content, 2) as $char) { $chars .= chr(intval(base_convert($char, 36, 10))); } return iconv('GBK//TRANSLIT', 'UTF-8', $chars); } } //设置应用数据表前缀 if (!function_exists('set_miniapp_database_prefix')) { /** * 设置应用数据表前缀 * @param string $dir 应用目录名 * @return bool */ function set_miniapp_database_prefix($dir) { if (!defined('MINIAPP_DATABASE_PREFIX')) { //应用表前缀 $miniapp_database_prefix = ''; //获取应用config/version.php $version_file = root_path() . 'app' . DS . $dir . DS . 'config' . DS . 'version.php'; if (file_exists($version_file)) { $version = include $version_file; isset($version['database']['prefix']) && $miniapp_database_prefix = $version['database']['prefix']; } //设置一个常量:应用表前缀 $miniapp_database_prefix && define('MINIAPP_DATABASE_PREFIX', $miniapp_database_prefix); } return true; } } //一维数组根据$parent_id的值转为多维数组 if (!function_exists('deal_list_to_tree')) { /** * 方法 deal_list_to_tree,一维数组根据$parent_id的值转为多维数组 * * @param array $data 待处理的一维数组 * @param string $pkName 用于转化为多维数组的主键字段 * @param string $pIdName 用于转化为多维数组的字段(根据该字段值转换) * @param string $childName 子级的字段名 * @param bool $is_empty_childrens 是否返回空的子数组(childrens[])(true:是,false:否) * @param string $rootId 根节点$pkName值 * * @return array $new_data 返回处理好的(多层级)多维数组 * */ function deal_list_to_tree($data, $pkName = 'id', $pIdName = 'parent_id', $childName = 'children_list', $is_empty_childrens = false, $rootId = '') { $new_data = []; foreach ($data as $sorData) { if ($sorData[$pIdName] == $rootId) { $res = deal_list_to_tree($data, $pkName, $pIdName, $childName, $is_empty_childrens, $sorData[$pkName]); if (!empty($res) && !$is_empty_childrens) { if (array_key_exists($childName, $sorData)) { if (array_key_exists($childName, $sorData)) { $sorData[$childName][] = $res[0]; } else { $sorData[$childName][] = $res; } } else { $sorData[$childName] = $res; } } $new_data[] = $sorData; } } return $new_data; } } //得到目录中所有静态资源的绝对路径 if (!function_exists('get_public_files')) { /** * 得到目录中所有静态资源的绝对路径 * @param string $pathName 要搜索的目录 * @param array $file_map 要取路径的数组 * @return bool */ function get_public_files($pathName, &$file_map) { //将结果保存在result变量中 $result = array(); $temp = array(); //判断传入的变量是否是目录 if (!is_dir($pathName) || !is_readable($pathName)) { return null; } //取出目录中的文件和子目录名,使用scandir函数 $allFiles = scandir($pathName); //遍历他们 foreach ($allFiles as $fileName) { //判断是否是.和..因为这两个东西神马也不是。。。 if (in_array($fileName, array('.', '..'))) { continue; } //路径加文件名 $fullName = $pathName . '/' . $fileName; //如果是目录的话就继续遍历这个目录 if (is_dir($fullName)) { //将这个目录中的文件信息存入到数组中 $result[$fullName] = get_public_files($fullName, $file_map); } else { //如果是文件就先存入临时变量 $temp[] = $fullName; $pathinfo = pathinfo($fullName); $pathinfo['path'] = $fullName; $file_map[] = $pathinfo; } } //取出文件 if ($temp) { foreach ($temp as $f) { $result[] = $f; } } return $result; } } if (!function_exists('is_write')) { /** * 判断 文件/目录 是否可写(取代系统自带的 is_writeable 函数) * * @param string $file 文件/目录 * @return boolean */ function is_write($file) { if (is_dir($file)) { $dir = $file; if ($fp = @fopen("$dir/test.txt", 'w')) { @fclose($fp); @unlink("$dir/test.txt"); $writeable = true; } else { $writeable = false; } } else { if ($fp = @fopen($file, 'a+')) { @fclose($fp); $writeable = true; } else { $writeable = false; } } return $writeable; } } if (!function_exists('format_human_date')) { /** * 格式化 UNIX 时间戳为人易读的字符串 * * @param int Unix 时间戳 * @param mixed $local 本地时间 * * @return string 格式化的日期字符串 */ function format_human_date($remote, $local = null) { $timediff = (is_null($local) || $local ? time() : $local) - $remote; $chunks = array( /*array(60 * 60 * 24 * 365, 'year'), array(60 * 60 * 24 * 30, 'month'), array(60 * 60 * 24 * 7, 'week'), array(60 * 60 * 24, 'day'), array(60 * 60, 'hour1'), array(60, 'minute1'), array(1, 'second1')*/ array(60 * 60 * 24 * 365, '年'), array(60 * 60 * 24 * 30, '月'), array(60 * 60 * 24 * 7, '周'), array(60 * 60 * 24, '天'), array(60 * 60, '小时'), array(60, '分钟'), array(1, '秒钟') ); for ($i = 0, $j = count($chunks); $i < $j; $i++) { $seconds = $chunks[$i][0]; $name = $chunks[$i][1]; if (($count = floor($timediff / $seconds)) != 0) { break; } } return "{$count}{$name}前"; } if (!function_exists('addon_exist')) { /** 插件是否存在 * @param $addon_name 插件目录 * @return bool */ function addon_exist($addon_name) { try { // 检查插件 \buwang\service\PluginService::check($addon_name); } catch (Throwable $e) { return \buwang\service\PluginService::setError($e->getMessage(), $e->getCode()); } return true; } } if (!function_exists('addon_error')) { /** 插件错误信息 * @return string */ function addon_error($default = '') { return \buwang\service\PluginService::getError($default); } } if (!function_exists('addon_hook')) { /** * 处理插件钩子 * @param string $event 钩子名称 * @param array|null $params 传入参数 * @param bool $once 是否只返回一个结果 * @param bool $error 没有此插件时是否抛异常 * @return mixed */ function addon_hook($event, $params = null, bool $once = false, $error = true) { try { if (strpos($event, ':') !== false) { $event = explode(':', $event); $addon_name = $event[0]; $event = $event[1]; } else { $addon_name = ''; } $result = Event::trigger($event, $params, $once); if (!$result) { //只抛插件异常 if ($error) throw new \buwang\exception\AddonException("未找到{$addon_name}插件对应的{$event}方法,调用{$event}方法失败"); return ''; } } catch (Throwable $e) { //只抛插件异常 throw new \buwang\exception\AddonException($e->getMessage(), $e->getCode()); } return $result[0]; } } } if (!function_exists('region_id_to_text')) { /** * @param int $region_id 区域编码 * @param int $level 几级区域,默认为省市区三级编码 * @return array */ function region_id_to_text(int $region_id, int $level = 3) { if (app('cacheService')::get("region:{$level}:{$region_id}")) { $res = json_decode(app('cacheService')::get("region:{$level}:{$region_id}"), true); } else { $province_code = $city_code = $county_code = 0; $province = $city = $county = ''; $level >= 1 && $province_code = substr($region_id, 0, 2) . '0000'; $level >= 2 && $city_code = substr($region_id, 0, 4) . '00'; $level >= 3 && $county_code = $region_id; $province_code && $province = \app\common\model\SysRegion::where('id', $province_code)->value('name'); $city_code && $city = \app\common\model\SysRegion::where('id', $city_code)->value('name'); $county_code && $county = \app\common\model\SysRegion::where('id', $county_code)->value('name'); $res = [$province, $city, $county]; //设置缓存 app('cacheService')::set("region:{$level}:{$region_id}", json_encode($res)); } return $res; } } if (!function_exists('make_dir')) { /** * 创建文件夹,如果存在多级目录。则逐级创建 * @param string $pathname The directory path. * @param int $mode * @return bool */ function make_dir($pathname, $mode = 0777) { if (is_dir($pathname)) { return true; } if (is_dir(dirname($pathname))) { return mkdir($pathname, $mode); } make_dir(dirname($pathname)); return mkdir($pathname, $mode); } }