zm
2021-04-09 93652ca875fc904a25a7f214adc548745573950a
commit | author | age
90c639 1 <?php
Z 2
3 /**
4  * 强调:此处不要出现 use 语句!
5  */
6
7 if (!function_exists('env')) {
8     /**
9      * Gets the value of an environment variable.
10      *
11      * @param string $key
12      * @param mixed $default
13      * @param string $delimiter
14      * @return mixed
15      */
16     function env($key, $default = null, $delimiter = '')
17     {
18         $value = getenv($key);
19
20         if ($value === false) {
21             return value($default);
22         }
23
24         switch (strtolower($value)) {
25             case 'true':
26             case '(true)':
27                 return true;
28             case 'false':
29             case '(false)':
30                 return false;
31             case 'empty':
32             case '(empty)':
33                 return '';
34             case 'null':
35             case '(null)':
36                 return;
37         }
38
39         if (strlen($value) > 1 && str_starts_with($value, '"') && str_ends_with($value, '"')) {
40             $value = substr($value, 1, -1);
41         }
42
43         if (strlen($delimiter) > 0) {
44             if (strlen($value) == 0) {
45                 $value = $default;
46             } else {
47                 $value = explode($delimiter, $value);
48             }
49         }
50
51         return $value;
52     }
53 }
54
55 if (!function_exists('value')) {
56     /**
57      * Return the default value of the given value.
58      *
59      * @param mixed $value
60      * @return mixed
61      */
62     function value($value)
63     {
64         return $value instanceof Closure ? $value() : $value;
65     }
66 }
67
68 if (!function_exists('str_starts_with')) {
69     /**
70      * Determine if a given string starts with a given substring.
71      *
72      * @param string $haystack
73      * @param string|array $needles
74      * @return bool
75      */
76     function str_starts_with($haystack, $needles)
77     {
78         foreach ((array)$needles as $needle) {
79             if ($needle !== '' && substr($haystack, 0, strlen($needle)) === (string)$needle) {
80                 return true;
81             }
82         }
83
84         return false;
85     }
86 }
87
88 if (!function_exists('str_ends_with')) {
89     /**
90      * Determine if a given string ends with a given substring.
91      *
92      * @param string $haystack
93      * @param string|array $needles
94      * @return bool
95      */
96     function str_ends_with($haystack, $needles)
97     {
98         foreach ((array)$needles as $needle) {
99             if (substr($haystack, -strlen($needle)) === (string)$needle) {
100                 return true;
101             }
102         }
103
104         return false;
105     }
106 }
107
108 if (!function_exists('define_once')) {
109     /**
110      * Define a const if not exists.
111      *
112      * @param string $name
113      * @param mixed $value
114      * @return bool
115      */
116     function define_once($name, $value = true)
117     {
118         return defined($name) or define($name, $value);
119     }
120 }
121
122 if (!function_exists('dd')) {
123     /**
124      * Dump the passed variable and end the script.
125      *
126      * @param mixed $arg
127      * @param bool $dumpAndDie
128      * @return void
129      */
130     function dd($arg, $dumpAndDie = true)
131     {
132         echo "<pre>";
133         // http_response_code(500);
134         \yii\helpers\VarDumper::dump($arg);
135         echo "</pre>";
136         if ($dumpAndDie) {
137             die(1);
138         }
139     }
140 }
141
142 if (!function_exists('array_column')) {
143     function array_column(array $input, $columnKey, $indexKey = null)
144     {
145         $array = array();
146         foreach ($input as $value) {
147             if (!array_key_exists($columnKey, $value)) {
148                 trigger_error("Key \"$columnKey\" does not exist in array");
149                 return false;
150             }
151             if (is_null($indexKey)) {
152                 $array[] = $value[$columnKey];
153             } else {
154                 if (!array_key_exists($indexKey, $value)) {
155                     trigger_error("Key \"$indexKey\" does not exist in array");
156                     return false;
157                 }
158                 if (!is_scalar($value[$indexKey])) {
159                     trigger_error("Key \"$indexKey\" does not contain scalar value");
160                     return false;
161                 }
162                 $array[$value[$indexKey]] = $value[$columnKey];
163             }
164         }
165         return $array;
166     }
167 }
168
169 if (!function_exists('make_dir')) {
170     /**
171      * Create the directory by pathname
172      * @param string $pathname The directory path.
173      * @param int $mode
174      * @return bool
175      */
176     function make_dir($pathname, $mode = 0777)
177     {
178         if (is_dir($pathname)) {
179             return true;
180         }
181         if (is_dir(dirname($pathname))) {
182             return mkdir($pathname, $mode);
183         }
184         make_dir(dirname($pathname));
185         return mkdir($pathname, $mode);
186     }
187 }
188
189
190 if (!function_exists('app_version')) {
191     /**
192      * @return string
193      */
194     function app_version()
195     {
196         if (!class_exists('\Yii')) {
197             return '0.0.0';
198         }
199         $versionFile = Yii::$app->basePath . '/version.json';
200         if (!file_exists($versionFile)) {
201             return '0.0.0';
202         }
203         $versionContent = file_get_contents($versionFile);
204         if (!$versionContent) {
205             return '0.0.0';
206         }
207         $versionData = json_decode($versionContent, true);
208         if (!$versionData) {
209             return '0.0.0';
210         }
211         return isset($versionData['version']) ? $versionData['version'] : '0.0.0';
212     }
213 }
214
215 if (!function_exists('hump')) {
216     /**
217      * @param string $words
218      * @param string $separator
219      * @return string
220      * 下划线转驼峰或者字符串第一个字母大写
221      */
222     function hump($words, $separator = '_')
223     {
224         if (strpos($words, $separator) !== false) {
225             $newWords = str_replace($separator, " ", strtolower($words));
226             return ltrim(str_replace(" ", "", ucwords($newWords)), $separator);
227         } else {
228             return ucfirst($words);
229         }
230     }
231 }
232
233 if (!function_exists('get_supported_image_lib')) {
234     /**
235      * 获取支持的图片处理库
236      * @return array
237      * @throws Exception
238      */
239     function get_supported_image_lib()
240     {
241         switch (true) {
242             case function_exists('gd_info'):
243                 return ['Gd'];
244             case class_exists('\Imagick') && method_exists((new \Imagick()), 'setImageOpacity'):
245                 return ['Imagick'];
246             default:
247                 return ['Gd'];
248         }
249         throw new Exception('找不到可处理图片的扩展,请检查PHP是否正确安装了GD或Imagick扩展。');
250     }
251 }
252
253 if (!function_exists('price_format')) {
254     define_once('PRICE_FORMAT_FLOAT', 'float');
255     define_once('PRICE_FORMAT_STRING', 'string');
256
257     /**
258      * @param $val
259      * @param string $returnType PRICE_FORMAT_FLOAT|PRICE_FORMAT_STRING
260      * @param int $decimals
261      * @return float|string
262      */
263     function price_format($val, $returnType = 'string', $decimals = 2)
264     {
265         $val = floatval($val);
266         $result = number_format($val, $decimals, '.', '');
267         if ($returnType === PRICE_FORMAT_FLOAT) {
268             return (float)$result;
269         }
270         return $result;
271     }
272 }
273
274 if (!function_exists('mysql_timestamp')) {
275     /**
276      * 生成mysql数据库时间戳(eg. 2000-01-01 12:00:00)
277      * @param integer $time
278      * @return false|string
279      */
280     function mysql_timestamp($time = null)
281     {
282         if ($time === null) {
283             $time = time();
284         }
285         return date('Y-m-d H:i:s', $time);
286     }
287 }
288
289 if (!function_exists('new_date')) {
290     function new_date($date)
291     {
292         if ($date == '0000-00-00 00:00:00') {
293             return '';
294         }
295
296         $time = strtotime($date);
297         $Y = date('Y', $time) . '.';
298         $m = date('m', $time) . '.';
299         $d = date('d', $time) . ' ';
300         $His = date('H:i:s', $time);
301         return $Y . $m . $d . $His;
302     }
303 }
304
305 if (!function_exists('get_request_uri')) {
306     /**
307      * 获取当前请求的uri
308      * @return string|string[]|null
309      * @throws Exception
310      */
311     function get_request_uri()
312     {
313         if (isset($_SERVER['X-Rewrite-Url'])) { // IIS
314             $requestUri = $_SERVER['X-Rewrite-Url'];
315         } elseif (isset($_SERVER['REQUEST_URI'])) {
316             $requestUri = $_SERVER['REQUEST_URI'];
317             if ($requestUri !== '' && $requestUri[0] !== '/') {
318                 $requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $requestUri);
319             }
320         } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0 CGI
321             $requestUri = $_SERVER['ORIG_PATH_INFO'];
322             if (!empty($_SERVER['QUERY_STRING'])) {
323                 $requestUri .= '?' . $_SERVER['QUERY_STRING'];
324             }
325         } else {
326             throw new Exception('Unable to determine the request URI.');
327         }
328         return $requestUri;
329     }
330 }
331
332 if (!function_exists('is_we7')) {
333     /**
334      * 判断是否是微擎版
335      * @return bool
336      */
337     function is_we7()
338     {
339         $moduleFile = __DIR__ . '/../module.php';
340         if (@file_exists($moduleFile)) {
341             if (mb_stripos(__DIR__, 'addons') !== false && mb_stripos(__DIR__, 'zjhj_bd') !== false) {
342                 return true;
343             }
344             return false;
345         } else {
346             return false;
347         }
348     }
349 }
350 if (!function_exists('is_we7_offline')) {
351     /**
352      * 判断是否是微擎离线版
353      * @return bool
354      */
355     function is_we7_offline()
356     {
357         if (!is_we7()) {
358             return false;
359         }
360         if (file_exists(__DIR__ . '/../module.php')) {
361             if (mb_stripos(__DIR__, 'addons') !== false) {
362                 if (mb_stripos(__DIR__, 'zjhj_bd_offline') !== false) {
363                     return true;
364                 }
365             }
366             return false;
367         } else {
368             return false;
369         }
370     }
371 }
372 if (!function_exists('RGBToHex')) {
373     /**
374      * RGB转 十六进制
375      * @param $rgb RGB颜色的字符串 如:rgb(255,255,255);
376      * @return string 十六进制颜色值 如:#FFFFFF
377      */
378     function RGBToHex($rgb)
379     {
380         $regexp = "/^rgb\(([0-9]{0,3})\,\s*([0-9]{0,3})\,\s*([0-9]{0,3})\)/";
381         $re = preg_match($regexp, $rgb, $match);
382         $re = array_shift($match);
383         $hexColor = "#";
384         $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
385         for ($i = 0; $i < 3; $i++) {
386             $r = null;
387             $c = $match[$i];
388             $hexAr = array();
389             while ($c >= 16) {
390                 $r = $c % 16;
391                 $c = ($c / 16) >> 0;
392                 array_push($hexAr, $hex[$r]);
393             }
394             array_push($hexAr, $hex[$c]);
395             $ret = array_reverse($hexAr);
396             $item = implode('', $ret);
397             $item = str_pad($item, 2, '0', STR_PAD_LEFT);
398             $hexColor .= $item;
399         }
400         return $hexColor;
401     }
402 }
403 if (!function_exists('hex2rgb')) {
404     /**
405      * 十六进制 转 RGB
406      */
407     function hex2rgb($hexColor)
408     {
409         $color = str_replace('#', '', $hexColor);
410         if (strlen($color) > 3) {
411             $rgb = array(
412                 'r' => hexdec(substr($color, 0, 2)),
413                 'g' => hexdec(substr($color, 2, 2)),
414                 'b' => hexdec(substr($color, 4, 2))
415             );
416         } else {
417             $color = $hexColor;
418             $r = substr($color, 0, 1) . substr($color, 0, 1);
419             $g = substr($color, 1, 1) . substr($color, 1, 1);
420             $b = substr($color, 2, 1) . substr($color, 2, 1);
421             $rgb = array(
422                 'r' => hexdec($r),
423                 'g' => hexdec($g),
424                 'b' => hexdec($b)
425             );
426         }
427         return $rgb;
428     }
429 }
430
431 if (!function_exists('table_exists')) {
432     /**
433      * 检查数据表是否存在
434      * @param $tableName
435      * @return bool
436      * @throws \yii\db\Exception
437      */
438     function table_exists($tableName)
439     {
440         $sql = "SHOW TABLES LIKE '{$tableName}';";
441         $result = Yii::$app->db->createCommand($sql)->queryAll();
442         if (is_array($result) && count($result)) {
443             return true;
444         } else {
445             return false;
446         }
447     }
448 }
449
450 if (!function_exists('sql_execute')) {
451
452
453     /**
454      * 执行SQL
455      * @param string $sql 要运行的SQL
456      * @param bool $split 自动拆分SQL
457      * @param bool $continueOnError 遇到错误继续执行
458      * @throws Exception
459      */
460     function sql_execute($sql, $split = true, $continueOnError = true)
461     {
462         if ($split) {
463             $list = SqlFormatter::splitQuery($sql);
464         } else {
465             $list = [$sql];
466         }
467         foreach ($list as $item) {
468             try {
469                 Yii::$app->db->createCommand($item)->execute();
470             } catch (Exception $exception) {
471                 if (!$continueOnError) {
472                     throw $exception;
473                 }
474             }
475         }
476     }
477 }
478
479 if (!function_exists('get_distance')) {
480     /**
481      * 求两个已知经纬度之间的距离,单位为米
482      *
483      * @param $lng1 Number 位置1经度
484      * @param $lat1 Number 位置1纬度
485      * @param $lng2 Number 位置2经度
486      * @param $lat2 Number 位置2纬度
487      * @return float 距离,单位米
488      */
489     function get_distance($lng1, $lat1, $lng2, $lat2)
490     {
491         // 将角度转为狐度
492         $radLat1 = deg2rad($lat1); //deg2rad()函数将角度转换为弧度
493         $radLat2 = deg2rad($lat2);
494         $radLng1 = deg2rad($lng1);
495         $radLng2 = deg2rad($lng2);
496         $a = $radLat1 - $radLat2;
497         $b = $radLng1 - $radLng2;
498         $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6378.137 * 1000;
499         return $s;
500     }
501 }
502
503 if (!function_exists('we7_table_name')) {
504     /**
505      * 返回微擎数据表对应的完整表名称(添加前缀)
506      * @param $name
507      * @return string
508      */
509     function we7_table_name($name)
510     {
511         $configFile = __DIR__ . '/../../../data/config.php';
512         if (!file_exists($configFile)) {
513             $prefix = 'ims_';
514         } else {
515             require $configFile;
516             if (isset($config['db']['master'])) {
517                 $prefix = $config['db']['master']['tablepre'];
518             } else {
519                 $prefix = 'ims_';
520             }
521         }
522         return $prefix . $name;
523     }
524 }
525
526 if (!function_exists('we7_setting')) {
527     /**
528      * 返回微擎配置信息
529      * @param string $name
530      * @return array|mixed
531      */
532     function we7_setting($name = '')
533     {
534         $configFile = __DIR__ . '/../../../data/config.php';
535         if (!file_exists($configFile)) {
536             $config = [];
537         } else {
538             require $configFile;
539             if (!empty($name) && isset($config['setting'][$name])) {
540                 return $config['setting'][$name];
541             }
542             if (isset($config['setting'])) {
543                 $config = $config['setting'];
544             } else {
545                 $config = [];
546             }
547         }
548         return $config;
549     }
550 }
551
552 if (!function_exists('remove_dir')) {
553     /**
554      * 删除文件夹
555      * @param $dir
556      * @return bool
557      */
558     function remove_dir($dir)
559     {
560         //先删除目录下的文件:
561         $dh = opendir($dir);
562         while ($file = readdir($dh)) {
563             if ($file != "." && $file != "..") {
564                 $fullpath = $dir . "/" . $file;
565                 if (!is_dir($fullpath)) {
566                     unlink($fullpath);
567                 } else {
568                     remove_dir($fullpath);
569                 }
570             }
571         }
572
573         closedir($dh);
574         //删除当前文件夹:
575         if (rmdir($dir)) {
576             return true;
577         } else {
578             return false;
579         }
580     }
581 }
582
583 if (!function_exists('is_point_in_polygon')) {
584     /**
585      * 判断一个坐标是否在一个多边形内(由多个坐标围成的)
586      * 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
587      * 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
588      * @param array $point 指定点坐标
589      * @param array $pts 多边形坐标 顺时针方向
590      * @return bool
591      */
592     function is_point_in_polygon($point, $pts)
593     {
594         $N = count($pts);
595         $boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
596         $intersectCount = 0;//cross points count of x
597         $precision = 2e-10; //浮点类型计算时候与0比较时候的容差
598         $p1 = 0;//neighbour bound vertices
599         $p2 = 0;
600         $p = $point; //测试点
601
602         $p1 = $pts[0];//left vertex
603         for ($i = 1; $i <= $N; ++$i) {//check all rays
604             // dump($p1);
605             if ($p['lng'] == $p1['lng'] && $p['lat'] == $p1['lat']) {
606                 return $boundOrVertex;//p is an vertex
607             }
608
609             $p2 = $pts[$i % $N];//right vertex
610             if ($p['lat'] < min($p1['lat'], $p2['lat']) || $p['lat'] > max($p1['lat'], $p2['lat'])) {
611                 //ray is outside of our interests
612                 $p1 = $p2;
613                 continue;//next ray left point
614             }
615
616             if ($p['lat'] > min($p1['lat'], $p2['lat']) && $p['lat'] < max($p1['lat'], $p2['lat'])) {
617                 //ray is crossing over by the algorithm (common part of)
618                 if ($p['lng'] <= max($p1['lng'], $p2['lng'])) {
619                     //x is before of ray
620                     if ($p1['lat'] == $p2['lat'] && $p['lng'] >= min($p1['lng'], $p2['lng'])) {
621                         //overlies on a horizontal ray
622                         return $boundOrVertex;
623                     }
624
625                     if ($p1['lng'] == $p2['lng']) {//ray is vertical
626                         if ($p1['lng'] == $p['lng']) {//overlies on a vertical ray
627                             return $boundOrVertex;
628                         } else {//before ray
629                             ++$intersectCount;
630                         }
631                     } else {//cross point on the left side
632                         $xinters = ($p['lat'] - $p1['lat']) * ($p2['lng'] - $p1['lng']) / ($p2['lat'] - $p1['lat']) + $p1['lng'];//cross point of lng
633                         if (abs($p['lng'] - $xinters) < $precision) {//overlies on a ray
634                             return $boundOrVertex;
635                         }
636
637                         if ($p['lng'] < $xinters) {//before ray
638                             ++$intersectCount;
639                         }
640                     }
641                 }
642             } else {//special case when ray is crossing through the vertex
643                 if ($p['lat'] == $p2['lat'] && $p['lng'] <= $p2['lng']) {//p crossing over p2
644                     $p3 = $pts[($i + 1) % $N]; //next vertex
645                     if ($p['lat'] >= min($p1['lat'], $p3['lat']) && $p['lat'] <= max($p1['lat'], $p3['lat'])) {
646                         //p.lat lies between p1.lat & p3.lat
647                         ++$intersectCount;
648                     } else {
649                         $intersectCount += 2;
650                     }
651                 }
652             }
653             $p1 = $p2;//next ray left point
654         }
655
656         if ($intersectCount % 2 == 0) {//偶数在多边形外
657             return false;
658         } else { //奇数在多边形内
659             return true;
660         }
661     }
662 }
663
664 if (!function_exists('generate_order_no')) {
665     /**
666      * 生成 前缀+24位数字的订单号
667      * @param string $prefix 前缀
668      * @return string
669      */
670     function generate_order_no($prefix = '')
671     {
672         $randLen = 6;
673         $id = base_convert(substr(uniqid(), 0 - $randLen), 16, 10);
674         if (strlen($id) > 10) {
675             $id = substr($id, -10);
676         } elseif (strlen($id) < 10) {
677             $rLen = 10 - strlen($id);
678             $id = $id . rand(pow(10, $rLen - 1), pow(10, $rLen) - 1);
679         }
680         $dateTimeStr = date('YmdHis');
681         return $prefix . $dateTimeStr . $id;
682     }
683 }
684
685 if (!function_exists('sha256')) {
686     /**
687      * @param string $data 要进行哈希运算的消息。
688      * @param bool $raw_output 设置为 TRUE 输出原始二进制数据, 设置为 FALSE 输出小写 16 进制字符串。
689      * @return string
690      * 进行sha256加密
691      */
692     function sha256($data, $raw_output = false)
693     {
694         return hash('sha256', $data, $raw_output);
695     }
696 }
697
698 if (!function_exists('array_insert')) {
699     function array_insert(&$array, $position, $item)
700     {
701         $first_array = array_splice($array, 0, $position);
702         $array = array_merge($first_array, [$item], $array);
703     }
704 }
705
706 if (!function_exists('filter_emoji')) {
707     /**
708      * 过滤emoji字符
709      * @param $str
710      * @return string|null
711      */
712     function filter_emoji($str)
713     {
714         $str = preg_replace_callback(
715             '/./u',
716             function (array $match) {
717                 return strlen($match[0]) >= 4 ? '' : $match[0];
718             },
719             $str);
720
721         return $str;
722     }
723 }
724 if (!function_exists('utf8_str_split')) {
725     /**
726      * 字符串转数组,支持UTF8中文
727      * @param $str
728      * @param int $split_len
729      * @return array|bool|mixed
730      */
731     function utf8_str_split($str, $split_len = 1)
732     {
733         if (!preg_match('/^[0-9]+$/', $split_len) || $split_len < 1)
734             return FALSE;
735
736         $len = mb_strlen($str, 'UTF-8');
737         if ($len <= $split_len)
738             return array($str);
739
740         preg_match_all('/.{' . $split_len . '}|[^x00]{1,' . $split_len . '}$/us', $str, $ar);
741
742         return $ar[0];
743     }
744 }
745
746 if (!function_exists('address_handle')) {
747     /**
748      * 地址串处理,输出省市区,支持 中国省市区详细地址 或 省市区详细地址的转换
749      * 例:中国浙江省嘉兴市南湖区中环南路1882号 输出 浙江省 嘉兴市 南湖区
750      * @param $address
751      * @return string
752      */
753     function address_handle($address)
754     {
755         $new_address = '';
756         $arr = utf8_str_split($address);
757         $num = 0;
758         $address_num = 0;
759         foreach ($arr as $item) {
760             if (($num < 2 && $item != '中' && $item != '国') || $num >= 2) {
761                 $new_address .= $item;
762                 if ($item == '省' || $item == '市' || $item == '区') {
763                     if ($address_num < 2) {
764                         $new_address .= ' ';
765                     }
766                     $address_num++;
767                 }
768                 $num++;
769                 if ($address_num >= 3) {
770                     break;
771                 }
772             }
773         }
774         return $new_address;
775     }
776 }
777
778 if (!function_exists('file_uri')) {
779     /**
780      * @param $path
781      * @return string[]
782      * 获取指定文件夹的物理路径及网络路径
783      */
784     function file_uri($path)
785     {
786         $root = Yii::$app->basePath;
787         if (!is_dir($root . $path)) {
788             make_dir($root . $path);
789         }
790         $webUri = '';
791         if (Yii::$app instanceof \yii\web\Application) {
792             $webRoot = Yii::$app->request->hostInfo . Yii::$app->request->baseUrl;
793             $webRoot = dirname($webRoot);
794             $webUri = $webRoot . $path;
795         }
796         return [
797             'local_uri' => $root . $path,
798             'web_uri' => $webUri
799         ];
800     }
801 }
802
803 if (!function_exists('get_client_ip')) {
804     /**
805      * 获取客户端ip
806      * @return array|false|mixed|string
807      */
808     function get_client_ip()
809     {
810         $ip = 'unknown';
811         if (isset(Yii::$app->request->remoteIP)) {
812             $ip = Yii::$app->request->remoteIP;
813         }
814         if ($_SERVER['REMOTE_ADDR']) {
815             $ip = $_SERVER['REMOTE_ADDR'];
816         } elseif (getenv('REMOTE_ADDR')) {
817             $ip = getenv('REMOTE_ADDR');
818         }
819         return $ip;
820     }
821 }