common.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2021 勾股工作室
  4. * @license https://opensource.org/licenses/Apache-2.0
  5. * @link https://www.gougucms.com
  6. */
  7. // 应用公共文件
  8. use think\facade\Cache;
  9. use think\facade\Config;
  10. use think\facade\Db;
  11. use think\facade\Request;
  12. //设置缓存
  13. function set_cache($key, $value, $date = 86400)
  14. {
  15. Cache::set($key, $value, $date);
  16. }
  17. //读取缓存
  18. function get_cache($key)
  19. {
  20. return Cache::get($key);
  21. }
  22. //清空缓存
  23. function clear_cache($key)
  24. {
  25. Cache::clear($key);
  26. }
  27. //读取文件配置
  28. function get_config($key)
  29. {
  30. return Config::get($key);
  31. }
  32. //读取系统配置
  33. function get_system_config($name,$key='')
  34. {
  35. $config=[];
  36. if (get_cache('system_config' . $name)) {
  37. $config = get_cache('system_config' . $name);
  38. } else {
  39. $conf = Db::name('config')->where('name',$name)->find();
  40. if($conf['content']){
  41. $config = unserialize($conf['content']);
  42. }
  43. set_cache('system_config' . $name, $config);
  44. }
  45. if($key==''){
  46. return $config;
  47. }
  48. else{
  49. if($config[$key]){
  50. return $config[$key];
  51. }
  52. }
  53. }
  54. //系统信息
  55. function get_system_info($key)
  56. {
  57. $system = [
  58. 'os' => PHP_OS,
  59. 'php' => PHP_VERSION,
  60. 'upload_max_filesize' => get_cfg_var("upload_max_filesize") ? get_cfg_var("upload_max_filesize") : "不允许上传附件",
  61. 'max_execution_time' => get_cfg_var("max_execution_time") . "秒 ",
  62. ];
  63. if (empty($key)) {
  64. return $system;
  65. } else {
  66. return $system[$key];
  67. }
  68. }
  69. //获取url参数
  70. function get_params($key = "")
  71. {
  72. return Request::instance()->param($key);
  73. }
  74. //生成一个不会重复的字符串
  75. function make_token()
  76. {
  77. $str = md5(uniqid(md5(microtime(true)), true));
  78. $str = sha1($str); //加密
  79. return $str;
  80. }
  81. //随机字符串,默认长度10
  82. function set_salt($num = 10)
  83. {
  84. $str = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
  85. $salt = substr(str_shuffle($str), 10, $num);
  86. return $salt;
  87. }
  88. //密码加密
  89. function set_password($pwd, $salt)
  90. {
  91. return md5(md5($pwd . $salt) . $salt);
  92. }
  93. //判断cms是否完成安装
  94. function is_installed()
  95. {
  96. static $isInstalled;
  97. if (empty($isInstalled)) {
  98. $isInstalled = file_exists(CMS_ROOT . 'config/install.lock');
  99. }
  100. return $isInstalled;
  101. }
  102. //判断cms是否存在模板
  103. function isTemplate($url='')
  104. {
  105. static $isTemplate;
  106. if (empty($isTemplate)) {
  107. $isTemplate = file_exists(CMS_ROOT . 'app/'.$url);
  108. }
  109. return $isTemplate;
  110. }
  111. /**
  112. * 返回json数据,用于接口
  113. * @param integer $code
  114. * @param string $msg
  115. * @param array $data
  116. * @param string $url
  117. * @param integer $httpCode
  118. * @param array $header
  119. * @param array $options
  120. * @return json
  121. */
  122. function to_assign($code = 0, $msg = "操作成功", $data = [], $url = '', $httpCode = 200, $header = [], $options = [])
  123. {
  124. $res = ['code' => $code];
  125. $res['msg'] = $msg;
  126. $res['url'] = $url;
  127. if (is_object($data)) {
  128. $data = $data->toArray();
  129. }
  130. $res['data'] = $data;
  131. $response = \think\Response::create($res, "json", $httpCode, $header, $options);
  132. throw new \think\exception\HttpResponseException($response);
  133. }
  134. /**
  135. * 适配layui数据列表的返回数据方法,用于接口
  136. * @param integer $code
  137. * @param string $msg
  138. * @param array $data
  139. * @param integer $httpCode
  140. * @param array $header
  141. * @param array $options
  142. * @return json
  143. */
  144. function table_assign($code = 0, $msg = '请求成功', $data = [], $httpCode = 200, $header = [], $options = [])
  145. {
  146. $res['code'] = $code;
  147. $res['msg'] = $msg;
  148. if (is_object($data)) {
  149. $data = $data->toArray();
  150. }
  151. if (!empty($data['total'])) {
  152. $res['count'] = $data['total'];
  153. } else {
  154. $res['count'] = 0;
  155. }
  156. $res['data'] = $data['data'];
  157. $response = \think\Response::create($res, "json", $httpCode, $header, $options);
  158. throw new \think\exception\HttpResponseException($response);
  159. }
  160. //菜单转为父子菜单
  161. function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'list', $root = 0)
  162. {
  163. // 创建Tree
  164. $tree = array();
  165. if (is_array($list)) {
  166. // 创建基于主键的数组引用
  167. $refer = array();
  168. foreach ($list as $key => $data) {
  169. $refer[$data[$pk]] = &$list[$key];
  170. }
  171. foreach ($list as $key => $data) {
  172. // 判断是否存在parent
  173. $parentId = $data[$pid];
  174. if ($root == $parentId) {
  175. $tree[$data[$pk]] = &$list[$key];
  176. } else {
  177. if (isset($refer[$parentId])) {
  178. $parent = &$refer[$parentId];
  179. $parent[$child][$data[$pk]] = &$list[$key];
  180. }
  181. }
  182. }
  183. }
  184. return $tree;
  185. }
  186. /**
  187. * 时间戳格式化
  188. * @param int $time
  189. * @param string $format 默认'Y-m-d H:i',x代表毫秒
  190. * @return string 完整的时间显示
  191. */
  192. function time_format($time = NULL, $format = 'Y-m-d H:i:s')
  193. {
  194. $usec = $time = $time === null ? '' : $time;
  195. if (strpos($time, '.')!==false) {
  196. list($usec, $sec) = explode(".", $time);
  197. } else {
  198. $sec = 0;
  199. }
  200. return $time != '' ? str_replace('x', $sec, date($format, intval($usec))) : '';
  201. }
  202. /**
  203. * 根据附件表的id返回url地址
  204. * @param [type] $id [description]
  205. */
  206. function get_file($id)
  207. {
  208. if ($id) {
  209. $geturl = \think\facade\Db::name("file")->where(['id' => $id])->find();
  210. if ($geturl['status'] == 1) {
  211. //审核通过
  212. //获取签名的URL
  213. $url = $geturl['filepath'];
  214. return $url;
  215. } elseif ($geturl['status'] == 0) {
  216. //待审核
  217. return '/static/admin/images/nonepic360x360.jpg';
  218. } else {
  219. //不通过
  220. return '/static/admin/images/nonepic360x360.jpg';
  221. }
  222. }
  223. return false;
  224. }
  225. function get_file_list($dir)
  226. {
  227. $list=[];
  228. if(is_dir($dir)){
  229. $info = opendir($dir);
  230. while (($file = readdir($info)) !== false) {
  231. //echo $file.'<br>';
  232. $pathinfo=pathinfo($file);
  233. if($pathinfo['extension']=='html'){ //只获取符合后缀的文件
  234. array_push($list, $pathinfo);
  235. }
  236. }
  237. closedir($info);
  238. }
  239. return $list;
  240. }
  241. //获取当前登录用户的信息
  242. function get_login_user($key = "")
  243. {
  244. $session_user = get_config('app.session_user');
  245. if (\think\facade\Session::has($session_user)) {
  246. $gougu_user = \think\facade\Session::get($session_user);
  247. if (!empty($key)) {
  248. if (isset($gougu_user[$key])) {
  249. return $gougu_user[$key];
  250. } else {
  251. return '';
  252. }
  253. } else {
  254. return $gougu_user;
  255. }
  256. } else {
  257. return '';
  258. }
  259. }
  260. /**
  261. * 判断访客是否是蜘蛛
  262. */
  263. function isRobot($except = '') {
  264. $ua = strtolower ( $_SERVER ['HTTP_USER_AGENT'] );
  265. $botchar = "/(baidu|google|spider|soso|yahoo|sohu-search|yodao|robozilla|AhrefsBot)/i";
  266. $except ? $botchar = str_replace ( $except . '|', '', $botchar ) : '';
  267. if (preg_match ( $botchar, $ua )) {
  268. return true;
  269. }
  270. return false;
  271. }
  272. /**
  273. * 客户操作日志
  274. * @param string $type 操作类型 login reg add edit view delete down join sign play order pay
  275. * @param string $param_str 操作内容
  276. * @param int $param_id 操作内容id
  277. * @param array $param 提交的参数
  278. */
  279. function add_user_log($type, $param_str = '', $param_id = 0, $param = [])
  280. {
  281. $request = request();
  282. $title = '未知操作';
  283. $type_action = get_config('log.user_action');
  284. if($type_action[$type]){
  285. $title = $type_action[$type];
  286. }
  287. if ($type == 'login') {
  288. $login_user = \think\facade\Db::name('User')->where(array('id' => $param_id))->find();
  289. if ($login_user['nickname'] == '') {
  290. $login_user['nickname'] = $login_user['name'];
  291. }
  292. if ($login_user['nickname'] == '') {
  293. $login_user['nickname'] = $login_user['username'];
  294. }
  295. } else {
  296. $login_user = get_login_user();
  297. if (empty($login_user)) {
  298. $login_user = [];
  299. $login_user['id'] = 0;
  300. $login_user['nickname'] = '游客';
  301. if(isRobot()){
  302. $login_user['nickname'] = '蜘蛛';
  303. $type = 'spider';
  304. $title = '爬行';
  305. }
  306. } else {
  307. if ($login_user['nickname'] == '') {
  308. $login_user['nickname'] = $login_user['username'];
  309. }
  310. }
  311. }
  312. $content = $login_user['nickname'] . '在' . date('Y-m-d H:i:s') . '执行了' . $title . '操作';
  313. if ($param_str != '') {
  314. $content = $login_user['nickname'] . '在' . date('Y-m-d H:i:s') . $title . '了' . $param_str;
  315. }
  316. $data = [];
  317. $data['uid'] = $login_user['id'];
  318. $data['nickname'] = $login_user['nickname'];
  319. $data['type'] = $type;
  320. $data['title'] = $title;
  321. $data['content'] = $content;
  322. $data['param_id'] = $param_id;
  323. $data['param'] = json_encode($param);
  324. $data['module'] = strtolower(app('http')->getName());
  325. $data['controller'] = strtolower(app('request')->controller());
  326. $data['function'] = strtolower(app('request')->action());
  327. $data['ip'] = app('request')->ip();
  328. $data['create_time'] = time();
  329. \think\facade\Db::name('UserLog')->strict(false)->field(true)->insert($data);
  330. }
  331. /**
  332. * 邮件发送
  333. * @param $to 接收人
  334. * @param string $subject 邮件标题
  335. * @param string $content 邮件内容(html模板渲染后的内容)
  336. * @throws Exception
  337. * @throws phpmailerException
  338. */
  339. function send_email($to, $subject = '', $content = '')
  340. {
  341. $mail = new PHPMailer\PHPMailer\PHPMailer();
  342. $email_config = \think\facade\Db::name('config')
  343. ->where('name', 'email')
  344. ->find();
  345. $config = unserialize($email_config['content']);
  346. $mail->CharSet = 'UTF-8'; //设定邮件编码,默认ISO-8859-1,如果发中文此项必须设置,否则乱码
  347. $mail->isSMTP();
  348. $mail->SMTPDebug = 0;
  349. //调试输出格式
  350. //$mail->Debugoutput = 'html';
  351. //smtp服务器
  352. $mail->Host = $config['smtp'];
  353. //端口 - likely to be 25, 465 or 587
  354. $mail->Port = $config['smtp_port'];
  355. if($mail->Port == '465'){
  356. $mail->SMTPSecure = 'ssl';// 使用安全协议
  357. }
  358. //Whether to use SMTP authentication
  359. $mail->SMTPAuth = true;
  360. //发送邮箱
  361. $mail->Username = $config['smtp_user'];
  362. //密码
  363. $mail->Password = $config['smtp_pwd'];
  364. //Set who the message is to be sent from
  365. $mail->setFrom($config['email'], $config['from']);
  366. //回复地址
  367. //$mail->addReplyTo('replyto@example.com', 'First Last');
  368. //接收邮件方
  369. if (is_array($to)) {
  370. foreach ($to as $v) {
  371. $mail->addAddress($v);
  372. }
  373. } else {
  374. $mail->addAddress($to);
  375. }
  376. $mail->isHTML(true);// send as HTML
  377. //标题
  378. $mail->Subject = $subject;
  379. //HTML内容转换
  380. $mail->msgHTML($content);
  381. $status = $mail->send();
  382. if ($status) {
  383. return true;
  384. } else {
  385. // echo "Mailer Error: ".$mail->ErrorInfo;// 输出错误信息
  386. // die;
  387. return false;
  388. }
  389. }
  390. /*
  391. * 下划线转驼峰
  392. * 思路:
  393. * step1.原字符串转小写,原字符串中的分隔符用空格替换,在字符串开头加上分隔符
  394. * step2.将字符串中每个单词的首字母转换为大写,再去空格,去字符串首部附加的分隔符.
  395. */
  396. function camelize($uncamelized_words,$separator='_')
  397. {
  398. $uncamelized_words = $separator. str_replace($separator, " ", strtolower($uncamelized_words));
  399. return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator );
  400. }
  401. /**
  402. * 驼峰命名转下划线命名
  403. * 思路:
  404. * 小写和大写紧挨一起的地方,加上分隔符,然后全部转小写
  405. */
  406. function uncamelize($camelCaps,$separator='_')
  407. {
  408. return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
  409. }
  410. /**
  411. * 防止xss
  412. */
  413. function cleanHtml($param){
  414. // 创建HTMLPurifier配置对象
  415. $config = HTMLPurifier_Config::createDefault();
  416. $config->set('HTML.DefinitionID', 'html5-definitions');
  417. $config->set('HTML.DefinitionRev', 1);
  418. $config->set('HTML.ForbiddenAttributes', ['width', 'height']);
  419. //$config->set('HTML.Allowed', 'p,b,a[href],pre[class],code,blockquote,img[src],table,tr,th,td,ul,li,ol,dl,dt,dd');
  420. $config->set('HTML.ForbiddenElements', array('script'), true);//设置拒绝使用的tagname
  421. if ($def = $config->maybeGetRawHTMLDefinition()) {
  422. $def->addElement('video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', [
  423. 'src' => 'URI',
  424. 'type' => 'Text',
  425. 'poster' => 'URI',
  426. 'preload' => 'Enum#auto,metadata,none',
  427. 'controls' => 'Bool',
  428. ]);
  429. $def->addElement('source', 'Block', 'Flow', 'Common', [
  430. 'src' => 'URI',
  431. 'type' => 'Text',
  432. ]);
  433. }
  434. // 创建HTMLPurifier对象
  435. $purifier = new HTMLPurifier($config);
  436. //防止xss,过滤输入并输出结果
  437. $param = $purifier->purify($param);
  438. // 使用正则表达式匹配不存在双引号或单引号的情况
  439. if (!preg_match('/["\']/', $param)) {
  440. return $param; // 字符串中不包含双引号或单引号,校验通过
  441. } else {
  442. throw new \think\exception\HttpException(404, '找不到页面'); // 字符串中包含双引号或单引号,校验未通过
  443. }
  444. }