GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 8a4525...04b2e6 )
by t
05:00 queued 40s
created

Strings::replace()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
/**
3
 * Class Strings
4
 *
5
 * @link https://www.icy2003.com/
6
 * @author icy2003 <[email protected]>
7
 * @copyright Copyright (c) 2017, icy2003
8
 */
9
10
namespace icy2003\php\ihelpers;
11
12
use Exception;
13
use icy2003\php\C;
14
use icy2003\php\I;
15
16
/**
17
 * 字符串类
18
 *
19
 * @test icy2003\php_tests\ihelpers\StringsTest
20
 */
21
class Strings
22
{
23
24
    /**
25
     * 返回字符串的字节长
26
     *
27
     * - 一个中文等于 3 字节
28
     *
29
     * @param string $string
30
     *
31
     * @return integer
32
     *
33
     * @tested
34
     */
35 2
    public static function byteLength($string)
36
    {
37 2
        return mb_strlen($string, '8bit');
38
    }
39
    /**
40
     * 返回字符个数
41
     *
42
     * - 一个中文就是 1 个
43
     *
44
     * @param string $string
45
     *
46
     * @return integer
47
     *
48
     * @tested
49
     */
50 9
    public static function length($string)
51
    {
52 9
        return mb_strlen($string, 'UTF-8');
53
    }
54
55
    /**
56
     * 随机数种子(数字)
57
     */
58
    const STRINGS_RANDOM_NUMBER = '0123456789';
59
60
    /**
61
     * 随机数种子(小写字母)
62
     */
63
    const STRINGS_RANDOM_LOWERCASE = 'abcdefghijklmnopqrstuvwxyz';
64
65
    /**
66
     * 随机数种子(大写字母)
67
     */
68
    const STRINGS_RANDOM_UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
69
70
    /**
71
     * 生成随机字符串
72
     *
73
     * @param integer $length 随机字符串的长度,默认 32
74
     * @param string $chars 字符列表,默认为0-9和大小写字母
75
     *
76
     * @return string
77
     *
78
     * @test
79
     */
80 1
    public static function random($length = 32, $chars = self::STRINGS_RANDOM_NUMBER . self::STRINGS_RANDOM_LOWERCASE . self::STRINGS_RANDOM_UPPERCASE)
81
    {
82 1
        $str = '';
83 1
        for ($i = 0; $i < $length; ++$i) {
84 1
            $str .= mb_substr($chars, mt_rand(0, self::length($chars) - 1), 1);
85
        }
86
87 1
        return $str;
88
    }
89
90
    /**
91
     * 小驼峰转化成下划线(如需要大写下划线,用 strtoupper 转化即可)
92
     *
93
     * @param string $string
94
     *
95
     * @return string
96
     *
97
     * @tested
98
     */
99 1
    public static function toUnderline($string)
100
    {
101 1
        return strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $string));
102
    }
103
104
    /**
105
     * 下划线转化为小驼峰(如需要大驼峰,用 ucfirst 转化即可)
106
     *
107
     * @param string $string
108
     *
109
     * @return string
110
     *
111
     * @tested
112
     */
113 3
    public static function toCamel($string)
114
    {
115
        return lcfirst(preg_replace_callback('/_+([a-z0-9_\x7f-\xff])/', function ($matches) {
116 1
            return ucfirst($matches[1]);
117 3
        }, strtolower($string)));
118
    }
119
120
    /**
121
     * 格式化成标题格式(每个单词首字母大写)
122
     *
123
     * @param string $string
124
     *
125
     * @return string
126
     *
127
     * @tested
128
     */
129 1
    public static function toTitle($string)
130
    {
131 1
        return mb_convert_case($string, MB_CASE_TITLE, 'UTF-8');
132
    }
133
134
    /**
135
     * 检查字符串是否以某字符串开头
136
     *
137
     * @param string $string
138
     * @param string $search 待搜索子字符串
139
     *
140
     * @return boolean
141
     *
142
     * @tested
143
     */
144 3
    public static function isStartsWith($string, $search)
145
    {
146 3
        return (string) $search !== "" && mb_strpos($string, $search) === 0;
147
    }
148
149
    /**
150
     * 检查字符串是否以某字符串结尾
151
     *
152
     * @param string $string
153
     * @param string $search 待搜索子字符串
154
     *
155
     * @return boolean
156
     *
157
     * @tested
158
     */
159 3
    public static function isEndsWith($string, $search)
160
    {
161 3
        return (string) $search !== "" && mb_substr($string, -static::length($search)) === $search;
162
    }
163
164
    /**
165
     * 检查字符串中是否包含某字符串
166
     *
167
     * @param string $string
168
     * @param string $search 待搜索子字符串
169
     * @param integer $pos 如果找到子串,则引用出子串的起始位置
170
     *
171
     * @return boolean
172
     *
173
     * @tested
174
     */
175 6
    public static function isContains($string, $search, &$pos = null)
176
    {
177 6
        return (string) $search !== "" && ($pos = mb_strpos($string, $search)) !== false;
178
    }
179
180
    /**
181
     * 在字符串里找子串的前部分
182
     *
183
     * @param string $string
184
     * @param string $search
185
     * @param integer $pos 如果找到子串,则引用出子串的起始位置
186
     *
187
     * @return string
188
     *
189
     * @tested
190
     */
191 1
    public static function partBefore($string, $search, &$pos = null)
192
    {
193 1
        if (self::isContains($string, $search, $pos)) {
194 1
            return mb_substr($string, 0, $pos);
195
        }
196 1
        return "";
197
    }
198
199
    /**
200
     * 在字符串里找子串的后部分
201
     *
202
     * @param string $string
203
     * @param string $search
204
     * @param integer $pos 如果找到子串,则引用出子串的起始位置
205
     *
206
     * @return string
207
     *
208
     * @tested
209
     */
210 1
    public static function partAfter($string, $search, &$pos = null)
211
    {
212 1
        if (self::isContains($string, $search, $pos)) {
213 1
            return mb_substr($string, $pos + self::length($search), self::length($string) - 1);
214
        }
215 1
        return "";
216
    }
217
218
    /**
219
     * 反转字符串,支持中文
220
     *
221
     * @param string $string
222
     *
223
     * @return string
224
     *
225
     * @tested
226
     */
227 1
    public static function reverse($string)
228
    {
229 1
        return implode('', array_reverse(self::split($string)));
230
    }
231
232
    /**
233
     * 把字符串打散为数组
234
     *
235
     * @param string $string
236
     *
237
     * @return array
238
     *
239
     * @tested
240
     */
241 4
    public static function split($string)
242
    {
243 4
        return (array) preg_split('/(?<!^)(?!$)/u', $string);
244
    }
245
246
    /**
247
     * 拆分成数组
248
     *
249
     * @param array|string $mixed 数组或者字符串
250
     * @param string $delimiter 分隔符,默认英文逗号(,)
251
     * @param boolean $combine 是否合并相同元素,默认 false,即不合并
252
     *
253
     * @return array
254
     *
255
     * @tested
256
     */
257 4
    public static function toArray($mixed, $delimiter = ',', $combine = false)
258
    {
259 4
        if (is_array($mixed)) {
260 4
            $mixed = implode($delimiter, $mixed);
261
        }
262 4
        $array = explode($delimiter, $mixed);
263 4
        if (true === $combine) {
264 1
            $array = Arrays::toPart($array);
265
        }
266 4
        return $array;
267
    }
268
269
    /**
270
     * 返回字符串的子串
271
     *
272
     * @param string $string
273
     * @param integer $start 起始位置
274
     * @param integer|null $length 子串长度,默认为 null,即返回剩下的部分
275
     *
276
     * @return string
277
     *
278
     * @tested
279
     */
280 4
    public static function sub($string, $start, $length = null)
281
    {
282 4
        return mb_substr($string, $start, $length);
283
    }
284
285
    /**
286
     * 字符串转数字
287
     *
288
     * - 正则为 `/^\d\.*\d*[e|E]/` 的字符串会……,这是 PHP 特性!如果你不喜欢 PHP,右上角
289
     *
290
     * @param string $string
291
     *
292
     * @return double
293
     *
294
     * @tested
295
     */
296 1
    public static function toNumber($string)
297
    {
298 1
        return (double) $string;
299
    }
300
301
    /**
302
     * 用回调将分隔符拆分出来的字符串执行后,用分隔符合并回去
303
     *
304
     * @param callback $callback 回调
305
     * @param string $string
306
     * @param string $delimiter 分隔符,默认英文逗号(,)
307
     *
308
     * @return string
309
     */
310 1
    public static function map($callback, $string, $delimiter = ',')
311
    {
312 1
        $arr = [];
313 1
        $parts = explode($delimiter, $string);
314 1
        foreach ($parts as $part) {
315 1
            $arr[] = I::call($callback, [$part]);
316
        }
317 1
        return implode($delimiter, $arr);
318
    }
319
320
    /**
321
     * 重复一个字符若干次
322
     *
323
     * @param string $char
324
     * @param integer $num
325
     * @param integer $maxLength 最大重复次数,默认不限制
326
     *
327
     * @return string
328
     */
329 1
    public static function repeat($char, $num, $maxLength = null)
330
    {
331 1
        $length = null === $maxLength ? $num : min($maxLength, $num);
332 1
        return str_repeat($char, $length);
333
    }
334
335
    /**
336
     * 生成密码 hash
337
     *
338
     * @param string $password 原始密码
339
     * @param integer $cost
340
     *
341
     * @return string
342
     */
343 1
    public static function generatePasswordHash($password, $cost = null)
344
    {
345 1
        null === $cost && $cost = 13;
346
        // PHP 5 >= 5.5.0, PHP 7
347 1
        if (function_exists('password_hash')) {
348 1
            return password_hash($password, PASSWORD_DEFAULT, ['cost' => $cost]);
349
        }
350
        C::assertNotTrue($cost < 4 || $cost > 31, 'cost 必须大于等于 4,小于等于 31');
351
        $salt = sprintf('$2y$%02d$', $cost);
352
        $salt .= str_replace('+', '.', substr(base64_encode(self::random(20)), 0, 22));
353
        $hash = crypt($password, $salt);
354
        C::assertNotTrue(!is_string($hash) || strlen($hash) !== 60, '未知错误');
355
        return $hash;
356
    }
357
358
    /**
359
     * 验证密码
360
     *
361
     * @param string $password 原始密码
362
     * @param string $hash HASH 后的密码,需配合 Strings::generatePasswordHash
363
     *
364
     * @return boolean
365
     */
366 1
    public static function validatePassword($password, $hash)
367
    {
368 1
        if (!is_string($password) || $password === '') {
0 ignored issues
show
introduced by
The condition is_string($password) is always true.
Loading history...
369
            return false;
370
        }
371 1
        $matches = [];
372 1
        if (!preg_match('/^\$2[axy]\$(\d\d)\$[\.\/0-9A-Za-z]{22}/', $hash, $matches)
373 1
            || $matches[1] < 4
374 1
            || $matches[1] > 30) {
375
            return false;
376
        }
377
        // PHP 5 >= 5.5.0, PHP 7
378 1
        if (function_exists('password_verify')) {
379 1
            return password_verify($password, $hash);
380
        }
381
382
        $test = crypt($password, $hash);
383
        $n = strlen($test);
384
        if ($n !== 60) {
385
            return false;
386
        }
387
        // PHP 5 >= 5.6.0, PHP 7
388
        if (function_exists('hash_equals')) {
389
            return hash_equals($test, $hash);
390
        }
391
392
        $test .= '\0';
393
        $hash .= '\0';
394
        $expectedLength = self::byteLength($test);
395
        $actualLength = self::byteLength($hash);
396
        $diff = $expectedLength - $actualLength;
397
        for ($i = 0; $i < $actualLength; $i++) {
398
            $diff |= (ord($hash[$i]) ^ ord($test[$i % $expectedLength]));
399
        }
400
401
        return $diff === 0;
402
    }
403
404
    /**
405
     * 字符串转成变量
406
     *
407
     * - 变量是被如:{{}}括起来的字符串
408
     * - 例如:{{var}}
409
     *
410
     * @param string $name
411
     * @param array $boundary 边界符,默认 ['{{', '}}']
412
     *
413
     * @return string
414
     */
415 1
    public static function toVariable($name, $boundary = ['{{', '}}'])
416
    {
417 1
        if (is_string($boundary)) {
0 ignored issues
show
introduced by
The condition is_string($boundary) is always false.
Loading history...
418 1
            $boundary = [$boundary, $boundary];
419
        }
420 1
        return self::isContains($name, $boundary[0]) ? $name : $boundary[0] . $name . $boundary[1];
421
    }
422
423
    /**
424
     * 判断一个字符串是否是变量
425
     *
426
     * @param string $name
427
     * @param array $boundary 边界符,默认 ['{{', '}}']
428
     *
429
     * @return boolean
430
     */
431 2
    public static function isVariable($name, $boundary = ['{{', '}}'])
432
    {
433 2
        return self::isStartsWith($name, $boundary[0]) && self::isEndsWith($name, $boundary[1]);
434
    }
435
436
    /**
437
     * 计算包含变量的字符串
438
     *
439
     * @param string $text
440
     * @param array $array 键值对形式:[{{键}} => 值]。如果键不是变量,则不会替换进 $text
441
     * @param array $boundary 边界符,默认 ['{{', '}}']
442
     *
443
     * @return string
444
     */
445 1
    public static function fromVariable($text, $array, $boundary = ['{{', '}}'])
446
    {
447 1
        $data = [];
448 1
        foreach ($array as $name => $value) {
449 1
            self::isVariable($name, $boundary) && $data[$name] = $value;
450
        }
451 1
        return str_replace(array_keys($data), array_values($data), $text);
452
    }
453
454
    /**
455
     * 判断两个字符串像不像
456
     *
457
     * - 图形验证码里经常有人把 o 看成 0,所以……
458
     * - 例如:hello 和 hell0 看起来是像的 (-w-)o~
459
     *
460
     * @param string $string1 第一个字符串
461
     * @param string $string2 第二个字符串
462
     * @param array $array 看起来像的字符的列表,默认 ['0o', 'yv', 'ij', '1l']
463
     *
464
     * @return boolean
465
     */
466 1
    public static function looksLike($string1, $string2, $array = ['0oO', 'yv', 'ij', '1lI'])
467
    {
468 1
        if (self::length($string1) !== self::length($string2)) {
469 1
            return false;
470
        }
471 1
        $array1 = self::split($string1);
472 1
        $array2 = self::split($string2);
473 1
        if (empty($array1)) {
474
            return true;
475
        }
476 1
        foreach ($array1 as $index => $char1) {
477 1
            $char1 = strtolower($char1);
478 1
            $char2 = strtolower($array2[$index]);
479 1
            $isEqual = false;
480 1
            if ($char1 == $char2) {
481 1
                $isEqual = true;
482
            }
483 1
            foreach ($array as $row) {
484 1
                if (self::isContains($row, $char1) && self::isContains($row, $char2)) {
485 1
                    $isEqual = true;
486 1
                    break;
487
                }
488
            }
489 1
            if (false === $isEqual) {
490 1
                break;
491
            }
492
        }
493 1
        return $isEqual;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $isEqual seems to be defined by a foreach iteration on line 476. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
494
    }
495
496
    /**
497
     * 拼音编码对应表
498
     *
499
     * @var array
500
     */
501
    private static $__pinyin = ['a' => -20319, 'ai' => -20317, 'an' => -20304, 'ang' => -20295, 'ao' => -20292, 'ba' => -20283, 'bai' => -20265, 'ban' => -20257, 'bang' => -20242, 'bao' => -20230, 'bei' => -20051, 'ben' => -20036, 'beng' => -20032, 'bi' => -20026, 'bian' => -20002, 'biao' => -19990, 'bie' => -19986, 'bin' => -19982, 'bing' => -19976, 'bo' => -19805, 'bu' => -19784, 'ca' => -19775, 'cai' => -19774, 'can' => -19763, 'cang' => -19756, 'cao' => -19751, 'ce' => -19746, 'ceng' => -19741, 'cha' => -19739, 'chai' => -19728, 'chan' => -19725, 'chang' => -19715, 'chao' => -19540, 'che' => -19531, 'chen' => -19525, 'cheng' => -19515, 'chi' => -19500, 'chong' => -19484, 'chou' => -19479, 'chu' => -19467, 'chuai' => -19289, 'chuan' => -19288, 'chuang' => -19281, 'chui' => -19275, 'chun' => -19270, 'chuo' => -19263, 'ci' => -19261, 'cong' => -19249, 'cou' => -19243, 'cu' => -19242, 'cuan' => -19238, 'cui' => -19235, 'cun' => -19227, 'cuo' => -19224, 'da' => -19218, 'dai' => -19212, 'dan' => -19038, 'dang' => -19023, 'dao' => -19018, 'de' => -19006, 'deng' => -19003, 'di' => -18996, 'dian' => -18977, 'diao' => -18961, 'die' => -18952, 'ding' => -18783, 'diu' => -18774, 'dong' => -18773, 'dou' => -18763, 'du' => -18756, 'duan' => -18741, 'dui' => -18735, 'dun' => -18731, 'duo' => -18722, 'e' => -18710, 'en' => -18697, 'er' => -18696, 'fa' => -18526, 'fan' => -18518, 'fang' => -18501, 'fei' => -18490, 'fen' => -18478, 'feng' => -18463, 'fo' => -18448, 'fou' => -18447, 'fu' => -18446, 'ga' => -18239, 'gai' => -18237, 'gan' => -18231, 'gang' => -18220, 'gao' => -18211, 'ge' => -18201, 'gei' => -18184, 'gen' => -18183, 'geng' => -18181, 'gong' => -18012, 'gou' => -17997, 'gu' => -17988, 'gua' => -17970, 'guai' => -17964, 'guan' => -17961, 'guang' => -17950, 'gui' => -17947, 'gun' => -17931, 'guo' => -17928, 'ha' => -17922, 'hai' => -17759, 'han' => -17752, 'hang' => -17733, 'hao' => -17730, 'he' => -17721, 'hei' => -17703, 'hen' => -17701, 'heng' => -17697, 'hong' => -17692, 'hou' => -17683, 'hu' => -17676, 'hua' => -17496, 'huai' => -17487, 'huan' => -17482, 'huang' => -17468, 'hui' => -17454, 'hun' => -17433, 'huo' => -17427, 'ji' => -17417, 'jia' => -17202, 'jian' => -17185, 'jiang' => -16983, 'jiao' => -16970, 'jie' => -16942, 'jin' => -16915, 'jing' => -16733, 'jiong' => -16708, 'jiu' => -16706, 'ju' => -16689, 'juan' => -16664, 'jue' => -16657, 'jun' => -16647, 'ka' => -16474, 'kai' => -16470, 'kan' => -16465, 'kang' => -16459, 'kao' => -16452, 'ke' => -16448, 'ken' => -16433, 'keng' => -16429, 'kong' => -16427, 'kou' => -16423, 'ku' => -16419, 'kua' => -16412, 'kuai' => -16407, 'kuan' => -16403, 'kuang' => -16401, 'kui' => -16393, 'kun' => -16220, 'kuo' => -16216, 'la' => -16212, 'lai' => -16205, 'lan' => -16202, 'lang' => -16187, 'lao' => -16180, 'le' => -16171, 'lei' => -16169, 'leng' => -16158, 'li' => -16155, 'lia' => -15959, 'lian' => -15958, 'liang' => -15944, 'liao' => -15933, 'lie' => -15920, 'lin' => -15915, 'ling' => -15903, 'liu' => -15889, 'long' => -15878, 'lou' => -15707, 'lu' => -15701, 'lv' => -15681, 'luan' => -15667, 'lue' => -15661, 'lun' => -15659, 'luo' => -15652, 'ma' => -15640, 'mai' => -15631, 'man' => -15625, 'mang' => -15454, 'mao' => -15448, 'me' => -15436, 'mei' => -15435, 'men' => -15419, 'meng' => -15416, 'mi' => -15408, 'mian' => -15394, 'miao' => -15385, 'mie' => -15377, 'min' => -15375, 'ming' => -15369, 'miu' => -15363, 'mo' => -15362, 'mou' => -15183, 'mu' => -15180, 'na' => -15165, 'nai' => -15158, 'nan' => -15153, 'nang' => -15150, 'nao' => -15149, 'ne' => -15144, 'nei' => -15143, 'nen' => -15141, 'neng' => -15140, 'ni' => -15139, 'nian' => -15128, 'niang' => -15121, 'niao' => -15119, 'nie' => -15117, 'nin' => -15110, 'ning' => -15109, 'niu' => -14941, 'nong' => -14937, 'nu' => -14933, 'nv' => -14930, 'nuan' => -14929, 'nue' => -14928, 'nuo' => -14926, 'o' => -14922, 'ou' => -14921, 'pa' => -14914, 'pai' => -14908, 'pan' => -14902, 'pang' => -14894, 'pao' => -14889, 'pei' => -14882, 'pen' => -14873, 'peng' => -14871, 'pi' => -14857, 'pian' => -14678, 'piao' => -14674, 'pie' => -14670, 'pin' => -14668, 'ping' => -14663, 'po' => -14654, 'pu' => -14645, 'qi' => -14630, 'qia' => -14594, 'qian' => -14429, 'qiang' => -14407, 'qiao' => -14399, 'qie' => -14384, 'qin' => -14379, 'qing' => -14368, 'qiong' => -14355, 'qiu' => -14353, 'qu' => -14345, 'quan' => -14170, 'que' => -14159, 'qun' => -14151, 'ran' => -14149, 'rang' => -14145, 'rao' => -14140, 're' => -14137, 'ren' => -14135, 'reng' => -14125, 'ri' => -14123, 'rong' => -14122, 'rou' => -14112, 'ru' => -14109, 'ruan' => -14099, 'rui' => -14097, 'run' => -14094, 'ruo' => -14092, 'sa' => -14090, 'sai' => -14087, 'san' => -14083, 'sang' => -13917, 'sao' => -13914, 'se' => -13910, 'sen' => -13907, 'seng' => -13906, 'sha' => -13905, 'shai' => -13896, 'shan' => -13894, 'shang' => -13878, 'shao' => -13870, 'she' => -13859, 'shen' => -13847, 'sheng' => -13831, 'shi' => -13658, 'shou' => -13611, 'shu' => -13601, 'shua' => -13406, 'shuai' => -13404, 'shuan' => -13400, 'shuang' => -13398, 'shui' => -13395, 'shun' => -13391, 'shuo' => -13387, 'si' => -13383, 'song' => -13367, 'sou' => -13359, 'su' => -13356, 'suan' => -13343, 'sui' => -13340, 'sun' => -13329, 'suo' => -13326, 'ta' => -13318, 'tai' => -13147, 'tan' => -13138, 'tang' => -13120, 'tao' => -13107, 'te' => -13096, 'teng' => -13095, 'ti' => -13091, 'tian' => -13076, 'tiao' => -13068, 'tie' => -13063, 'ting' => -13060, 'tong' => -12888, 'tou' => -12875, 'tu' => -12871, 'tuan' => -12860, 'tui' => -12858, 'tun' => -12852, 'tuo' => -12849, 'wa' => -12838, 'wai' => -12831, 'wan' => -12829, 'wang' => -12812, 'wei' => -12802, 'wen' => -12607, 'weng' => -12597, 'wo' => -12594, 'wu' => -12585, 'xi' => -12556, 'xia' => -12359, 'xian' => -12346, 'xiang' => -12320, 'xiao' => -12300, 'xie' => -12120, 'xin' => -12099, 'xing' => -12089, 'xiong' => -12074, 'xiu' => -12067, 'xu' => -12058, 'xuan' => -12039, 'xue' => -11867, 'xun' => -11861, 'ya' => -11847, 'yan' => -11831, 'yang' => -11798, 'yao' => -11781, 'ye' => -11604, 'yi' => -11589, 'yin' => -11536, 'ying' => -11358, 'yo' => -11340, 'yong' => -11339, 'you' => -11324, 'yu' => -11303, 'yuan' => -11097, 'yue' => -11077, 'yun' => -11067, 'za' => -11055, 'zai' => -11052, 'zan' => -11045, 'zang' => -11041, 'zao' => -11038, 'ze' => -11024, 'zei' => -11020, 'zen' => -11019, 'zeng' => -11018, 'zha' => -11014, 'zhai' => -10838, 'zhan' => -10832, 'zhang' => -10815, 'zhao' => -10800, 'zhe' => -10790, 'zhen' => -10780, 'zheng' => -10764, 'zhi' => -10587, 'zhong' => -10544, 'zhou' => -10533, 'zhu' => -10519, 'zhua' => -10331, 'zhuai' => -10329, 'zhuan' => -10328, 'zhuang' => -10322, 'zhui' => -10315, 'zhun' => -10309, 'zhuo' => -10307, 'zi' => -10296, 'zong' => -10281, 'zou' => -10274, 'zu' => -10270, 'zuan' => -10262, 'zui' => -10260, 'zun' => -10256, 'zuo' => -10254];
502
503
    /**
504
     * 字符串转拼音
505
     *
506
     * @param string $text
507
     * @param boolean $returnArray 是否拆分返回数组,默认 false
508
     *
509
     * @return array|string
510
     */
511 2
    public static function toPinyin($text, $returnArray = false)
512
    {
513 2
        $text = Charset::convertTo($text, 'GB2312');
514 2
        $result = [];
515 2
        $length = strlen($text);
516 2
        for ($i = 0; $i < $length; $i++) {
517 2
            $p = ord(substr($text, $i, 1));
518 2
            if ($p > 160) {
519 2
                $p = $p * 256 + ord(substr($text, ++$i, 1)) - 65536;
520
            }
521 2
            if ($p > 0 && $p < 160) {
522 1
                $result[] = chr($p);
523 2
            } elseif ($p < -20319 || $p > -10247) {
524
                return '';
525
            } else {
526 2
                $res = '';
527 2
                foreach (self::$__pinyin as $pin => $code) {
528 2
                    if ($code > $p) {
529 2
                        break;
530
                    }
531 2
                    $res = $pin;
532
                }
533 2
                $result[] = $res;
534
            }
535
        }
536 2
        if (true === $returnArray) {
537 2
            return $result;
538 1
        } elseif (false === $returnArray) {
0 ignored issues
show
introduced by
The condition false === $returnArray is always true.
Loading history...
539 1
            return implode('', $result);
540
        } else {
541 1
            return implode((string) $returnArray, $result);
542
        }
543
    }
544
545
    /**
546
     * 字符串转拼音首字母
547
     *
548
     * @param string $text
549
     * @param boolean $returnArray 是否拆分返回数组,默认 false
550
     *
551
     * @return array|string
552
     */
553 1
    public static function toPinyinFirst($text, $returnArray = false)
554
    {
555 1
        $array = (array) self::toPinyin($text, true);
556
        $result = array_map(function ($row) {
557 1
            return self::sub($row, 0, 1);
558 1
        }, $array);
559 1
        if (true === $returnArray) {
560 1
            return $result;
561 1
        } elseif (false === $returnArray) {
0 ignored issues
show
introduced by
The condition false === $returnArray is always true.
Loading history...
562 1
            return implode('', $result);
563
        } else {
564 1
            return implode((string) $returnArray, $result);
565
        }
566
    }
567
568
    /**
569
     * 隐藏部分文字
570
     *
571
     * - 只支持三种模式,例如:3?4、?3、3?,数字代表显示的字符数,默认模式为:3?4
572
     *
573
     * @param string $string
574
     * @param string $hideChar 被替换的字符,默认为:****
575
     * @param string $mode 替换模式,默认为:3?4,即保留前 3 字符,后 4 字符,隐藏中间
576
     *
577
     * @return string
578
     */
579 1
    public static function hide($string, $hideChar = '****', $mode = '3?4')
580
    {
581 1
        $length = self::length($string);
582 1
        $modeArray = self::split($mode);
583 1
        $modeCount = Arrays::count($modeArray);
584 1
        C::assertFalse(1 !== Arrays::count($modeArray, '?'), '模式错误,只允许有且仅有一个 ? 符,例如:3?4');
585 1
        if ($length <= array_sum($modeArray)) {
586 1
            return $string;
587
        }
588 1
        if (3 === Arrays::count($modeArray)) {
589 1
            C::assertTrue('?' === $modeArray[1], '模式错误,三段时,? 符必须在中间,例如:3?4');
590 1
            return self::sub($string, 0, $modeArray[0]) . $hideChar . self::sub($string, $length - $modeArray[2], $modeArray[2]);
591 1
        } elseif (2 === $modeCount) {
592 1
            if ('?' === $modeArray[0]) {
593 1
                return $hideChar . self::sub($string, $length - $modeArray[1], $modeArray[1]);
594
            } else {
595 1
                return self::sub($string, 0, $modeArray[0]) . $hideChar;
596
            }
597
        } else {
598 1
            throw new Exception("支持模式有三种,例如:3?4、?3、3?");
599
        }
600
    }
601
602
    /**
603
     * 多次换行
604
     *
605
     * @param integer $num 换行次数
606
     *
607
     * @return string
608
     */
609
    public static function eol($num = 1)
610
    {
611
        return str_repeat(PHP_EOL, $num);
612
    }
613
614
    /**
615
     * 返回字符串占用行数
616
     *
617
     * @param string $string
618
     *
619
     * @return integer
620
     */
621
    public static function lineNumber($string)
622
    {
623
        $array = explode(PHP_EOL, $string);
624
        return Arrays::count($array);
625
    }
626
627
    /**
628
     * 字符串替换
629
     *
630
     * @param string $string
631
     * @param array $replaceArray 键值对替换
632
     * @param integer $count 如果给定,则引用返回替换次数
633
     *
634
     * @return string
635
     */
636 50
    public static function replace($string, $replaceArray, &$count = null)
637
    {
638 50
        return str_replace(array_keys($replaceArray), array_values($replaceArray), $string, $count);
639
    }
640
}
641