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
Pull Request — master (#5)
by t
63:46
created

StringsTrait::hide()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 19
c 1
b 0
f 0
nc 7
nop 3
dl 0
loc 25
rs 8.8333
1
<?php
2
/**
3
 * Trait 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
14
/**
15
 * 字符串扩展
16
 */
17
trait StringsTrait
18
{
19
    /**
20
     * 生成密码 hash
21
     *
22
     * @param string $password 原始密码
23
     * @param integer $cost
24
     *
25
     * @return string
26
     */
27
    public static function generatePasswordHash($password, $cost = null)
28
    {
29
        null === $cost && $cost = 13;
30
        // PHP 5 >= 5.5.0, PHP 7
31
        if (function_exists('password_hash')) {
32
            return password_hash($password, PASSWORD_DEFAULT, ['cost' => $cost]);
33
        }
34
        if ($cost < 4 || $cost > 31) {
35
            throw new Exception('cost 必须大于等于 4,小于等于 31');
36
        }
37
        $salt = sprintf('$2y$%02d$', $cost);
38
        $salt .= str_replace('+', '.', substr(base64_encode(self::random(20)), 0, 22));
39
        $hash = crypt($password, $salt);
40
        if (!is_string($hash) || strlen($hash) !== 60) {
41
            throw new Exception('未知错误');
42
        }
43
        return $hash;
44
    }
45
46
    /**
47
     * 验证密码
48
     *
49
     * @param string $password 原始密码
50
     * @param string $hash HASH 后的密码,需配合 Strings::generatePasswordHash
51
     *
52
     * @return boolean
53
     */
54
    public static function validatePassword($password, $hash)
55
    {
56
        if (!is_string($password) || $password === '') {
0 ignored issues
show
introduced by
The condition is_string($password) is always true.
Loading history...
57
            return false;
58
        }
59
        $matches = [];
60
        if (!preg_match('/^\$2[axy]\$(\d\d)\$[\.\/0-9A-Za-z]{22}/', $hash, $matches)
61
            || $matches[1] < 4
62
            || $matches[1] > 30) {
63
            return false;
64
        }
65
        // PHP 5 >= 5.5.0, PHP 7
66
        if (function_exists('password_verify')) {
67
            return password_verify($password, $hash);
68
        }
69
70
        $test = crypt($password, $hash);
71
        $n = strlen($test);
72
        if ($n !== 60) {
73
            return false;
74
        }
75
        // PHP 5 >= 5.6.0, PHP 7
76
        if (function_exists('hash_equals')) {
77
            return hash_equals($test, $hash);
78
        }
79
80
        $test .= '\0';
81
        $hash .= '\0';
82
        $expectedLength = self::byteLength($test);
83
        $actualLength = self::byteLength($hash);
84
        $diff = $expectedLength - $actualLength;
85
        for ($i = 0; $i < $actualLength; $i++) {
86
            $diff |= (ord($hash[$i]) ^ ord($test[$i % $expectedLength]));
87
        }
88
89
        return $diff === 0;
90
    }
91
92
    /**
93
     * 字符串转成变量
94
     *
95
     * - 变量是被如:{{}}括起来的字符串
96
     * - 例如:{{var}}
97
     *
98
     * @param string $name
99
     * @param array $boundary 边界符,默认 ['{{', '}}']
100
     *
101
     * @return string
102
     */
103
    public static function toVariable($name, $boundary = ['{{', '}}'])
104
    {
105
        if (is_string($boundary)) {
0 ignored issues
show
introduced by
The condition is_string($boundary) is always false.
Loading history...
106
            $boundary = [$boundary, $boundary];
107
        }
108
        return self::isContains($name, $boundary[0]) ? $name : $boundary[0] . $name . $boundary[1];
109
    }
110
111
    /**
112
     * 判断一个字符串是否是变量
113
     *
114
     * @param string $name
115
     * @param array $boundary 边界符,默认 ['{{', '}}']
116
     *
117
     * @return boolean
118
     */
119
    public static function isVariable($name, $boundary = ['{{', '}}'])
120
    {
121
        return self::isStartsWith($name, $boundary[0]) && self::isEndsWith($name, $boundary[1]);
122
    }
123
124
    /**
125
     * 计算包含变量的字符串
126
     *
127
     * @param string $text
128
     * @param array $array 键值对形式:[{{键}} => 值]。如果键不是变量,则不会替换进 $text
129
     * @param array $boundary 边界符,默认 ['{{', '}}']
130
     *
131
     * @return string
132
     */
133
    public static function fromVariable($text, $array, $boundary = ['{{', '}}'])
134
    {
135
        $data = [];
136
        foreach ($array as $name => $value) {
137
            self::isVariable($name, $boundary) && $data[$name] = $value;
138
        }
139
        return str_replace(array_keys($data), array_values($data), $text);
140
    }
141
142
    /**
143
     * 判断两个字符串像不像
144
     *
145
     * - 图形验证码里经常有人把 o 看成 0,所以……
146
     * - 例如:hello 和 hell0 看起来是像的 (-w-)o~
147
     *
148
     * @param string $string1 第一个字符串
149
     * @param string $string2 第二个字符串
150
     * @param array $array 看起来像的字符的列表,默认 ['0o', 'yv', 'ij', '1l']
151
     *
152
     * @return boolean
153
     */
154
    public static function looksLike($string1, $string2, $array = ['0oO', 'yv', 'ij', '1lI'])
155
    {
156
        $array1 = self::split($string1);
157
        $array2 = self::split($string2);
158
        foreach ($array1 as $index => $char1) {
159
            $char1 = strtolower($char1);
160
            $char2 = strtolower($array2[$index]);
161
            $isEqual = false;
162
            if ($char1 == $char2) {
163
                $isEqual = true;
164
            }
165
            foreach ($array as $row) {
166
                if (self::isContains($row, $char1) && self::isContains($row, $char2)) {
167
                    $isEqual = true;
168
                    break;
169
                }
170
            }
171
            if (false === $isEqual) {
172
                break;
173
            }
174
        }
175
        return $isEqual;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $isEqual seems to be defined by a foreach iteration on line 158. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
176
    }
177
178
    /**
179
     * 拼音编码对应表
180
     *
181
     * @var array
182
     */
183
    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];
184
185
    /**
186
     * 字符串转拼音
187
     *
188
     * @param string $text
189
     * @param boolean $returnArray 是否拆分返回数组,默认 false
190
     *
191
     * @return mixed
192
     */
193
    public static function toPinyin($text, $returnArray = false)
194
    {
195
        $text = Charset::convertTo($text, 'GB2312');
196
        $result = [];
197
        $length = strlen($text);
198
        for ($i = 0; $i < $length; $i++) {
199
            $p = ord(substr($text, $i, 1));
200
            if ($p > 160) {
201
                $p = $p * 256 + ord(substr($text, ++$i, 1)) - 65536;
202
            }
203
            if ($p > 0 && $p < 160) {
204
                $result[] = chr($p);
205
            } elseif ($p < -20319 || $p > -10247) {
206
                return '';
207
            } else {
208
                $res = '';
209
                foreach (self::$__pinyin as $pin => $code) {
210
                    if ($code > $p) {
211
                        break;
212
                    }
213
                    $res = $pin;
214
                }
215
                $result[] = $res;
216
            }
217
        }
218
        return true === $returnArray ? $result : implode('', $result);
219
    }
220
221
    /**
222
     * 字符串转拼音首字母
223
     *
224
     * @param string $text
225
     * @param boolean $returnArray 是否拆分返回数组,默认 false
226
     *
227
     * @return mixed
228
     */
229
    public static function toPinyinFirst($text, $returnArray = false)
230
    {
231
        $array = self::toPinyin($text, true);
232
        $result = array_map(function ($row) {
233
            return self::sub($row, 0, 1);
234
        }, $array);
0 ignored issues
show
Bug introduced by
It seems like $array can also be of type string; however, parameter $arr1 of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

234
        }, /** @scrutinizer ignore-type */ $array);
Loading history...
235
        return true === $returnArray ? $result : implode('', $result);
236
    }
237
238
    /**
239
     * 隐藏部分文字
240
     *
241
     * - 只支持三种模式,例如:3?4、?3、3?,数字代表显示的字符数,默认模式为:3?4
242
     *
243
     * @param string $string
244
     * @param string $hideChar 被替换的字符,默认为:****
245
     * @param string $mode 替换模式,默认为:3?4,即保留前 3 字符,后 4 字符,隐藏中间
246
     *
247
     * @return string
248
     */
249
    public static function hide($string, $hideChar = '****', $mode = '3?4')
250
    {
251
        $length = self::length($string);
252
        $modeArray = self::split($mode);
253
        $modeCount = Arrays::count($modeArray);
254
        if (1 !== Arrays::count($modeArray, '?')) {
255
            throw new Exception("模式错误,只允许有且仅有一个 ? 符,例如:3?4");
256
        }
257
        if ($length <= array_sum($modeArray)) {
258
            return $string;
259
        }
260
        if (3 === Arrays::count($modeArray)) {
261
            if ('?' === $modeArray[1]) {
262
                return self::sub($string, 0, $modeArray[0]) . $hideChar . self::sub($string, $length - $modeArray[2], $modeArray[2]);
263
            } else {
264
                throw new Exception("模式错误,三段时,? 符必须在中间,例如:3?4");
265
            }
266
        } elseif (2 === $modeCount) {
267
            if ('?' === $modeArray[0]) {
268
                return $hideChar . self::sub($string, $length - $modeArray[1], $modeArray[1]);
269
            } else {
270
                return self::sub($string, 0, $modeArray[0]) . $hideChar;
271
            }
272
        } else {
273
            throw new Exception("支持模式有三种,例如:3?4、?3、3?");
274
        }
275
    }
276
277
    /**
278
     * 多次换行
279
     *
280
     * @param integer $num 换行次数
281
     *
282
     * @return string
283
     */
284
    public static function eol($num = 1)
285
    {
286
        return str_repeat(PHP_EOL, $num);
287
    }
288
289
    /**
290
     * 返回字符串占用行数
291
     *
292
     * @param string $string
293
     *
294
     * @return integer
295
     */
296
    public static function lineNumber($string)
297
    {
298
        $array = explode(PHP_EOL, $string);
299
        return Arrays::count($array);
300
    }
301
}
302