helper.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. <?php
  2. if (!function_exists('matchLatLng')) {
  3. function matchLatLng($latlng)
  4. {
  5. $match = "/^\d{1,3}\.\d{1,30}$/";
  6. return preg_match($match, $latlng) ? $latlng : 0;
  7. }
  8. }
  9. if (!function_exists('getDistanceBuilder')) {
  10. function getDistanceBuilder($lat, $lng)
  11. {
  12. return "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN((" . matchLatLng($lat) . " * PI() / 180 - latitude * PI() / 180) / 2), 2) + COS(" . matchLatLng($lat) . " * PI() / 180) * COS(latitude * PI() / 180) * POW(SIN((" . matchLatLng($lng) . " * PI() / 180 - longitude * PI() / 180) / 2), 2))) * 1000) AS distance";
  13. }
  14. }
  15. if (!function_exists('error_stop')) {
  16. function error_stop($msg = '', $code = 0, $data = null, $status_code = 200, $header = [])
  17. {
  18. $result = [
  19. 'code' => $code ?: 0,
  20. 'msg' => $msg,
  21. 'data' => $data
  22. ];
  23. $response = \think\Response::create($result, 'json', $status_code)->header($header);
  24. throw new \think\exception\HttpResponseException($response);
  25. }
  26. }
  27. /**
  28. * 过滤掉字符串中的 sql 关键字
  29. */
  30. if (!function_exists('filter_sql')) {
  31. function filter_sql($str)
  32. {
  33. $str = strtolower($str); // 转小写
  34. $str = str_replace("and", "", $str);
  35. $str = str_replace("execute", "", $str);
  36. $str = str_replace("update", "", $str);
  37. $str = str_replace("count", "", $str);
  38. $str = str_replace("chr", "", $str);
  39. $str = str_replace("mid", "", $str);
  40. $str = str_replace("master", "", $str);
  41. $str = str_replace("truncate", "", $str);
  42. $str = str_replace("char", "", $str);
  43. $str = str_replace("declare", "", $str);
  44. $str = str_replace("select", "", $str);
  45. $str = str_replace("create", "", $str);
  46. $str = str_replace("delete", "", $str);
  47. $str = str_replace("insert", "", $str);
  48. $str = str_replace("union", "", $str);
  49. $str = str_replace("alter", "", $str);
  50. $str = str_replace("into", "", $str);
  51. $str = str_replace("'", "", $str);
  52. $str = str_replace("or", "", $str);
  53. $str = str_replace("=", "", $str);
  54. return $str;
  55. }
  56. }
  57. /**
  58. * 检测字符串是否是版本号
  59. */
  60. if (!function_exists('is_version_str')) {
  61. /**
  62. * 检测字符串是否是版本号
  63. * @param string $version
  64. * @return boolean
  65. */
  66. function is_version_str($version)
  67. {
  68. $match = "/^([0-9]\d|[0-9])(\.([0-9]\d|\d))+/";
  69. return preg_match($match, $version) ? true : false;
  70. }
  71. }
  72. /**
  73. * 删除目录
  74. */
  75. if (!function_exists('rmdirs')) {
  76. /**
  77. * 删除目录
  78. * @param string $dirname 目录
  79. * @param bool $withself 是否删除自身
  80. * @return boolean
  81. */
  82. function rmdirs($dirname, $withself = true)
  83. {
  84. if (!is_dir($dirname)) {
  85. return false;
  86. }
  87. $files = new RecursiveIteratorIterator(
  88. new RecursiveDirectoryIterator($dirname, RecursiveDirectoryIterator::SKIP_DOTS),
  89. RecursiveIteratorIterator::CHILD_FIRST
  90. );
  91. foreach ($files as $fileinfo) {
  92. if ($fileinfo->isDir() === 'rmdir') rmdir(($fileinfo->getRealPath()));
  93. if ($fileinfo->isDir() === 'unlink') unlink(($fileinfo->getRealPath()));
  94. }
  95. if ($withself) {
  96. @rmdir($dirname);
  97. }
  98. return true;
  99. }
  100. }
  101. /**
  102. * 复制目录
  103. */
  104. if (!function_exists('copydirs')) {
  105. /**
  106. * 复制目录
  107. * @param string $source 源文件夹
  108. * @param string $dest 目标文件夹
  109. */
  110. function copydirs($source, $dest)
  111. {
  112. if (!is_dir($dest)) {
  113. @mkdir($dest, 0755, true);
  114. }
  115. foreach ($iterator = new RecursiveIteratorIterator(
  116. new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
  117. RecursiveIteratorIterator::SELF_FIRST
  118. ) as $item) {
  119. if ($item->isDir()) {
  120. $sontDir = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
  121. if (!is_dir($sontDir)) {
  122. @mkdir($sontDir, 0755, true);
  123. }
  124. } else {
  125. copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
  126. }
  127. }
  128. }
  129. }
  130. if (!function_exists('is_url')) {
  131. function is_url($url)
  132. {
  133. if (preg_match("/^(http:\/\/|https:\/\/)/", $url)) {
  134. return true;
  135. }
  136. return false;
  137. }
  138. }
  139. /**
  140. * 快捷设置跨域请求头(跨域中间件失效时,一些特殊拦截时候需要用到)
  141. */
  142. if (!function_exists('set_cors')) {
  143. /**
  144. * 快捷设置跨域请求头(跨域中间件失效时,一些特殊拦截时候需要用到)
  145. *
  146. * @return void
  147. */
  148. function set_cors()
  149. {
  150. $header = [
  151. 'Access-Control-Allow-Origin' => '*', // 规避跨域
  152. 'Access-Control-Allow-Credentials' => 'true',
  153. 'Access-Control-Max-Age' => 1800,
  154. 'Access-Control-Allow-Methods' => 'GET, POST, PATCH, PUT, DELETE, OPTIONS',
  155. 'Access-Control-Allow-Headers' => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-CSRF-TOKEN, X-Requested-With, platform',
  156. ];
  157. // 直接将 header 添加到响应里面
  158. foreach ($header as $name => $val) {
  159. header($name . (!is_null($val) ? ':' . $val : ''));
  160. }
  161. if (request()->isOptions()) {
  162. // 如果是预检直接返回响应,后续都不在执行
  163. exit;
  164. }
  165. }
  166. }
  167. if (!function_exists('sheep_config')) {
  168. /**
  169. * 获取SheepAdmin配置
  170. * @param string $code 配置名
  171. * @return string
  172. */
  173. function sheep_config(string $code, $cache = true)
  174. {
  175. return \app\admin\model\shopro\Config::getConfigs($code, $cache);
  176. }
  177. }
  178. /**
  179. * 获取前端用户
  180. */
  181. if (!function_exists('auth_user')) {
  182. function auth_user($throwException = false)
  183. {
  184. if (\app\common\library\Auth::instance()->isLogin()) {
  185. return \app\common\library\Auth::instance()->getUser();
  186. }
  187. if ($throwException) {
  188. error_stop('请登录后操作', 0, null, 401);
  189. }
  190. return null;
  191. }
  192. }
  193. /**
  194. * 获取管理员信息
  195. */
  196. if (!function_exists('auth_admin')) {
  197. function auth_admin()
  198. {
  199. if (\app\admin\library\Auth::instance()->isLogin()) {
  200. $admin = \app\admin\library\Auth::instance()->getUserInfo(); // 这里获取的是个数组,转为模型
  201. if ($admin) {
  202. return \app\admin\model\shopro\Admin::where('id', $admin['id'])->find();
  203. }
  204. }
  205. return null;
  206. }
  207. }
  208. if (!function_exists('has_redis')) {
  209. /**
  210. * 判断是否配置好了 redis
  211. *
  212. * @param boolean $is_exception 是否 抛出异常
  213. * @return boolean
  214. */
  215. function has_redis($is_exception = false, $cache = true)
  216. {
  217. $key = 'has_redis';
  218. if ($cache && cache('?' . $key)) {
  219. // 使用缓存,并且存在缓存
  220. return cache($key);
  221. }
  222. $error_msg = '';
  223. try {
  224. addons\shopro\facade\Redis::ping();
  225. } catch (\BadFunctionCallException $e) {
  226. // 缺少扩展
  227. $error_msg = $e->getMessage() ? $e->getMessage() : "缺少 redis 扩展";
  228. } catch (\RedisException $e) {
  229. // 连接拒绝
  230. \think\Log::write('redis connection redisException fail: ' . $e->getMessage());
  231. $error_msg = $e->getMessage() ? $e->getMessage() : "redis 连接失败";
  232. } catch (\Exception $e) {
  233. // 异常
  234. \think\Log::write('redis connection fail: ' . $e->getMessage());
  235. $error_msg = $e->getMessage() ? $e->getMessage() : "redis 连接异常";
  236. }
  237. cache($key, ($error_msg ? false : true), 10); // 保存缓存
  238. if ($error_msg) {
  239. if ($is_exception) {
  240. throw new \Exception($error_msg);
  241. } else {
  242. return false;
  243. }
  244. }
  245. return true;
  246. }
  247. }
  248. if (!function_exists('redis_cache')) {
  249. /**
  250. * 缓存管理
  251. * @param mixed $name 缓存名称,如果为数组表示进行缓存设置
  252. * @param mixed $value 缓存值
  253. * @param mixed $options 缓存参数
  254. * @param string $tag 缓存标签
  255. * @return mixed
  256. */
  257. function redis_cache($name = null, $value = '', $ttl = null)
  258. {
  259. $cache = new \addons\shopro\library\RedisCache;
  260. if ($name === null) {
  261. return $cache;
  262. } elseif ('' === $value) {
  263. // 获取缓存
  264. return 0 === strpos($name, '?') ? $cache->has(substr($name, 1)) : $cache->get($name);
  265. } elseif (is_null($value)) {
  266. // 删除缓存
  267. return $cache->delete($name);
  268. } else {
  269. // 缓存数据
  270. return $cache->set($name, $value, $ttl);
  271. }
  272. }
  273. }
  274. /**
  275. * 检测系统必要环境
  276. */
  277. if (!function_exists('check_env')) {
  278. function check_env($need = [], $is_throw = true)
  279. {
  280. $need = is_string($need) ? [$need] : $need;
  281. // 检测是否安装浮点数运算扩展
  282. if (in_array('bcmath', $need)) {
  283. if (!extension_loaded('bcmath')) {
  284. if ($is_throw) {
  285. error_stop('请安装浮点数扩展 【bcmath】');
  286. } else {
  287. return false;
  288. }
  289. }
  290. }
  291. // 检测是否安装了队列
  292. if (in_array('queue', $need)) {
  293. if (!class_exists(\think\Queue::class)) {
  294. if ($is_throw) {
  295. error_stop('请安装 【topthink/think-queue:v1.1.6 队列扩展】');
  296. } else {
  297. return false;
  298. }
  299. }
  300. }
  301. // 检查是否有分销功能
  302. if (in_array('commission', $need)) {
  303. if (!class_exists(\addons\shopro\listener\Commission::class)) {
  304. if ($is_throw) {
  305. error_stop('请先升级 【shopro】');
  306. } else {
  307. return false;
  308. }
  309. }
  310. }
  311. // 检查是否安装了支付扩展包
  312. if (in_array('yansongda', $need)) {
  313. //读取插件的状态,epay为插件标识
  314. $info = get_addon_info('epay');
  315. if (!$info || !$info['state']) {
  316. if ($is_throw) {
  317. error_stop('请确保【微信支付宝整合插件】已安装并启用');
  318. } else {
  319. return false;
  320. }
  321. }
  322. if (version_compare($info['version'], '1.3.0') < 0) {
  323. if ($is_throw) {
  324. error_stop('请安装【微信支付宝整合插件】v1.3.0 及以上版本');
  325. } else {
  326. return false;
  327. }
  328. }
  329. }
  330. return true;
  331. }
  332. }
  333. if (!function_exists('diff_in_time')) {
  334. /**
  335. * 计算两个时间相差多少天,多少小时,多少分钟
  336. *
  337. * @param int $first 要比较的第一个时间 Carbon 或者时间格式
  338. * @param mixed $second 要比较的第二个时间 Carbon 或者时间格式
  339. * @param bool $format 是否格式化为字符串
  340. * @return string|array
  341. */
  342. function diff_in_time($first, $second = null, $format = true, $simple = false)
  343. {
  344. $second = is_null($second) ? time() : $second;
  345. $diff = abs($first - $second); // 取绝对值
  346. $years = floor($diff / (86400 * 365));
  347. $surplus = $diff % (86400 * 365);
  348. $days = floor($surplus / 86400);
  349. $surplus = $surplus % 86400;
  350. $hours = floor($surplus / 3600);
  351. $surplus = $surplus % 3600;
  352. $minutes = floor($surplus / 60);
  353. $surplus = $surplus % 60;
  354. $second = $surplus;
  355. if (!$format) {
  356. return compact('years', 'days', 'hours', 'minutes', 'second');
  357. }
  358. $format_text = '';
  359. $start = false;
  360. if ($years) {
  361. $start = true;
  362. $format_text .= $years . '年';
  363. }
  364. if ($start || $days) {
  365. $start = true;
  366. $format_text .= ($days % 365) . '天';
  367. }
  368. if ($start || $hours) {
  369. $start = true;
  370. $format_text .= ($hours % 24) . '时';
  371. }
  372. if ($start || $minutes) {
  373. $start = true;
  374. $format_text .= ($minutes % 60) . '分钟';
  375. }
  376. if (($start || $second) && !$simple) {
  377. $start = true;
  378. $format_text .= ($second % 60) . '秒';
  379. }
  380. return $format_text;
  381. }
  382. }
  383. if (!function_exists('short_var_export')) {
  384. /**
  385. * 使用短标签打印或返回数组结构
  386. * @param mixed $data
  387. * @param boolean $return 是否返回数据
  388. * @return string
  389. */
  390. function short_var_export($expression, $return = FALSE)
  391. {
  392. $export = var_export($expression, TRUE);
  393. $patterns = [
  394. "/array \(/" => '[',
  395. "/^([ ]*)\)(,?)$/m" => '$1]$2',
  396. "/=>[ ]?\n[ ]+\[/" => '=> [',
  397. "/([ ]*)(\'[^\']+\') => ([\[\'])/" => '$1$2 => $3',
  398. ];
  399. $export = preg_replace(array_keys($patterns), array_values($patterns), $export);
  400. if ((bool)$return) return $export;
  401. else echo $export;
  402. }
  403. }
  404. if (!function_exists('get_sn')) {
  405. /**
  406. * 获取唯一编号
  407. *
  408. * @param mixed $id 唯一标识
  409. * @param string $type 类型
  410. * @return string
  411. */
  412. function get_sn($id, $type = '')
  413. {
  414. $id = (string)$id;
  415. $rand = $id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
  416. $sn = date('Yhis') . $rand;
  417. $id = str_pad($id, (24 - strlen($sn)), '0', STR_PAD_BOTH);
  418. return $type . $sn . $id;
  419. }
  420. }
  421. if (!function_exists('string_hide')) {
  422. /**
  423. * 隐藏部分字符串
  424. *
  425. * @param string $string 原始字符串
  426. * @param int $start 开始位置
  427. * @return string
  428. */
  429. function string_hide($string, $start = 2)
  430. {
  431. if (mb_strlen($string) > $start) {
  432. $hide = mb_substr($string, 0, $start) . '***';
  433. } else {
  434. $hide = $string . '***';
  435. }
  436. return $hide;
  437. }
  438. }
  439. if (!function_exists('account_hide')) {
  440. /**
  441. * 隐藏账号部分字符串
  442. *
  443. * @param string $string 原始字符串
  444. * @param int $start 开始位置
  445. * @param int $end 开始位置
  446. * @return string
  447. */
  448. function account_hide($string, $start = 2, $end = 2)
  449. {
  450. $hide = mb_substr($string, 0, $start) . '*****' . mb_substr($string, -$end);
  451. return $hide;
  452. }
  453. }
  454. if (!function_exists('gen_random_str')) {
  455. /**
  456. * 随机生成字符串
  457. * @param int $length 字符串长度
  458. * @return bool $upper 默认小写
  459. */
  460. function gen_random_str($length = 10, $upper = false)
  461. {
  462. if ($upper) {
  463. $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  464. } else {
  465. $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
  466. }
  467. $randomString = '';
  468. for ($i = 0; $i < $length; $i++) {
  469. $randomString .= $characters[rand(0, strlen($characters) - 1)];
  470. }
  471. return $randomString;
  472. }
  473. }
  474. if (!function_exists('random_mobile')) {
  475. /**
  476. * 随机生成字符串
  477. * @param int $length 字符串长度
  478. * @return bool $upper 默认小写
  479. */
  480. function random_mobile()
  481. {
  482. $mobile = '1';
  483. $second = [3, 5, 7, 8, 9];
  484. return $mobile . $second[array_rand($second)] . mt_rand(100000000, 999999999);
  485. }
  486. }
  487. if (!function_exists('random_email')) {
  488. /**
  489. * 随机生成字符串
  490. * @param int $length 字符串长度
  491. * @return bool $upper 默认小写
  492. */
  493. function random_email($prefix = '')
  494. {
  495. $first = [
  496. random_mobile(),
  497. gen_random_str(mt_rand(6, 15), mt_rand(0, 1)),
  498. ];
  499. $first_name = $prefix ?: $first[array_rand($first)];
  500. $suffix = [
  501. '@gmail.com',
  502. '@msn.com',
  503. '@qq.com',
  504. '@163.com',
  505. '@163.net',
  506. '@126.com',
  507. '@139.com',
  508. '@189.cn',
  509. '@sina.com',
  510. ];
  511. return $first_name . $suffix[array_rand($suffix)];
  512. }
  513. }
  514. if (!function_exists('format_log_error')) {
  515. /**
  516. * 格式化记录日志,重要地方使用
  517. *
  518. * @param object $error
  519. * @param string $name
  520. * @param string $message
  521. * @return void
  522. */
  523. function format_log_error($error, $name = 'QUEUE', $message = '')
  524. {
  525. $logInfo = [
  526. "========== $name LOG INFO BEGIN ==========",
  527. '[ Message ] ' . var_export('[' . $error->getCode() . ']' . $error->getMessage() . ' ' . $message, true),
  528. '[ File ] ' . var_export($error->getFile() . ':' . $error->getLine(), true),
  529. '[ Trace ] ' . var_export($error->getTraceAsString(), true),
  530. "============================================= $name LOG INFO ENDED ==========",
  531. ];
  532. $logInfo = implode(PHP_EOL, $logInfo) . PHP_EOL;
  533. \think\Log::error($logInfo);
  534. }
  535. }
  536. if (!function_exists('set_token_in_header')) {
  537. /**
  538. * 设置token令牌到响应的header中
  539. *
  540. * @param string $token
  541. * @return void
  542. */
  543. function set_token_in_header($token)
  544. {
  545. header("Access-Control-Expose-Headers: token");
  546. header("token: $token");
  547. }
  548. }
  549. if (!function_exists('morph_to')) {
  550. /**
  551. * 多态关联
  552. *
  553. * @param array|object $items
  554. * @param array $morphs
  555. * @param array $fields
  556. * @return array|object
  557. */
  558. function morph_to($items, $morphs, $fields)
  559. {
  560. if ($items instanceof \think\Paginator) {
  561. $data = $items->items();
  562. } else if ($items instanceof \think\Collection) {
  563. $data = $items;
  564. } else {
  565. $data = collection($items);
  566. }
  567. $allIds = [];
  568. foreach ($data as $item) {
  569. $allIds[$item[$fields[0]]][] = $item[$fields[1]];
  570. }
  571. $morphsData = [];
  572. foreach ($allIds as $key => $ids) {
  573. $morphData = (new $morphs[$key])::where('id', 'in', $ids)->select();
  574. $morphsData[$key] = array_column($morphData, null, 'id');
  575. }
  576. $morph_key = strstr($fields[0], '_', true);
  577. foreach ($data as &$item) {
  578. $item->{$morph_key} = $morphsData[$item[$fields[0]]][$item[$fields[1]]] ?? null;
  579. }
  580. if ($items instanceof \think\Paginator) {
  581. $items->data = $items;
  582. } else {
  583. $items = $data;
  584. }
  585. return $items;
  586. }
  587. }
  588. if (!function_exists('image_resize_save')) {
  589. /**
  590. * 图片裁剪缩放并保存
  591. * @param string $image_url 图片地址
  592. * @param string $save_path 保存地址
  593. * @param string $target_w 目标宽度
  594. * @param string $target_h 目标高度
  595. * @return void
  596. */
  597. function image_resize_save($image_url, $save_path, $target_w = 200, $target_h = 200)
  598. {
  599. $dst_h = 200;
  600. $dst_w = 200;
  601. list($src_w, $src_h) = getimagesize($image_url);
  602. $dst_scale = $dst_h / $dst_w; // 目标图像长宽比,正方形
  603. $src_scale = $src_h / $src_w; // 原图长宽比
  604. if ($src_scale >= $dst_scale) { // 过高
  605. $w = intval($src_w);
  606. $h = intval($dst_scale * $w);
  607. $x = 0;
  608. $y = ($src_h - $h) / 3;
  609. } else { // 过宽
  610. $h = intval($src_h);
  611. $w = intval($h / $dst_scale);
  612. $x = ($src_w - $w) / 2;
  613. $y = 0;
  614. }
  615. // 剪裁
  616. $source = imagecreatefrompng($image_url);
  617. $croped = imagecreatetruecolor($w, $h);
  618. imagecopy($croped, $source, 0, 0, $x, $y, $src_w, $src_h);
  619. if ($w > $dst_w) {
  620. $scale = $dst_w / $w;
  621. $target = imagecreatetruecolor($dst_w, $dst_h);
  622. $final_w = intval($w * $scale);
  623. $final_h = intval($h * $scale);
  624. imagecopyresampled($target, $croped, 0, 0, 0, 0, $final_w, $final_h, $w, $h);
  625. } else {
  626. $target = $source;
  627. }
  628. // 创建目录
  629. $dir = dirname($save_path);
  630. if (!is_dir($dir)) {
  631. @mkdir($dir, 0755, true);
  632. }
  633. imagejpeg($target, $save_path);
  634. imagedestroy($target);
  635. }
  636. }
  637. if (!function_exists('get_addonnames')) {
  638. /**
  639. * 获取已安装的插件
  640. *
  641. * @param $type enable:已安装启用的插件,disabled:已安装禁用的插件,all:所有插件
  642. */
  643. function get_addonnames($type = 'enable')
  644. {
  645. $key = 'shopro_fa_addons_list';
  646. if (cache('?' . $key)) {
  647. $addons = cache($key);
  648. } else {
  649. $addons = get_addon_list();
  650. cache($key, $addons, 60);
  651. }
  652. $addonList = [
  653. 'all' => [],
  654. 'enable' => [],
  655. 'disabled' => []
  656. ];
  657. foreach ($addons as $addon_name => $info) {
  658. $addonList['all'][] = $addon_name;
  659. $addonList[($info['state'] == 1 ? 'enable' : 'disabled')][] = $addon_name;
  660. }
  661. return $addonList[$type] ?? [];
  662. }
  663. }
  664. if (!function_exists('client_unique')) {
  665. /**
  666. * 获取客户端唯一标识
  667. *
  668. * @return boolean
  669. */
  670. function client_unique()
  671. {
  672. // $httpName = app('http')->getName();
  673. $httpName = '';
  674. $url = request()->baseUrl();
  675. $ip = request()->ip();
  676. $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
  677. $key = $httpName . ':' . $url . ':' . $ip . ':' . $user_agent;
  678. return md5($key);
  679. }
  680. }
  681. /**
  682. * 删除 sql mode 指定模式,或者直接关闭 sql mode
  683. */
  684. if (!function_exists('closeStrict')) {
  685. function closeStrict($modes = [])
  686. {
  687. $modes = array_filter(is_array($modes) ? $modes : [$modes]);
  688. $result = \think\Db::query("SELECT @@session.sql_mode ");
  689. $newModes = $oldModes = explode(',', ($result[0]['@@session.sql_mode'] ?? ''));
  690. if ($modes) {
  691. foreach ($modes as $mode) {
  692. $delkey = array_search($mode, $newModes);
  693. if ($delkey !== false) {
  694. unset($newModes[$delkey]);
  695. }
  696. }
  697. $newModes = join(',', array_values(array_filter($newModes)));
  698. } else {
  699. $newModes = '';
  700. }
  701. \think\Db::execute("set session sql_mode='" . $newModes . "'");
  702. return $oldModes;
  703. }
  704. }
  705. /**
  706. * 重新打开被关闭的 sql mode
  707. */
  708. if (!function_exists('recoverStrict')) {
  709. function recoverStrict($modes = [], $append = false)
  710. {
  711. if ($append) {
  712. $result = \think\Db::query("SELECT @@session.sql_mode ");
  713. $oldModes = explode(',', ($result[0]['@@session.sql_mode'] ?? ''));
  714. $modes = array_values(array_filter(array_unique(array_merge($oldModes, $modes))));
  715. }
  716. \think\Db::execute("set session sql_mode='" . join(',', $modes) . "'");
  717. }
  718. }
  719. // **********************以下方法请忽略*********************
  720. // 当前方法直接返回 $value, 请忽略该方法
  721. if (!function_exists('config_show')) {
  722. function config_show($value, $data)
  723. {
  724. if (class_exists(\app\common\library\ShowHow::class)) {
  725. return \app\common\library\ShowHow::configHide($value, $data);
  726. }
  727. return $value;
  728. }
  729. }
  730. // 当前方法直接返回 $config, 请忽略该方法
  731. if (!function_exists('pay_config_show')) {
  732. function pay_config_show($config)
  733. {
  734. if (class_exists(\app\common\library\ShowHow::class)) {
  735. return \app\common\library\ShowHow::payConfigHide($config);
  736. }
  737. return $config;
  738. }
  739. }
  740. // 当前方法全部返回 true, 请忽略该方法
  741. if (!function_exists('operate_filter')) {
  742. function operate_filter($is_exception = true)
  743. {
  744. if (class_exists(\app\common\library\ShowHow::class)) {
  745. return \app\common\library\ShowHow::operateFilter($is_exception);
  746. }
  747. return true;
  748. }
  749. }
  750. // 当前方法全部返回 true, 请忽略
  751. if (!function_exists('operate_disabled')) {
  752. function operate_disabled($is_exception = true)
  753. {
  754. if (class_exists(\app\common\library\ShowHow::class)) {
  755. return \app\common\library\ShowHow::operateDisabled($is_exception);
  756. }
  757. return true;
  758. }
  759. }