1 | <?php |
||||
2 | |||||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||||
3 | namespace Jxlwqq\IdValidator; |
||||
4 | |||||
5 | /** |
||||
6 | * Trait Generator. |
||||
7 | */ |
||||
0 ignored issues
–
show
|
|||||
8 | trait Generator |
||||
9 | { |
||||
10 | /** |
||||
11 | * 生成顺序码 |
||||
12 | * |
||||
13 | * @param int $sex 性别 |
||||
14 | * |
||||
15 | * @return int|string |
||||
16 | */ |
||||
17 | private function _generatorOrderCode($sex) |
||||
18 | { |
||||
19 | $orderCode = mt_rand(111, 999); |
||||
20 | |||||
21 | if ($sex !== null && $sex !== $orderCode % 2) { |
||||
22 | $orderCode -= 1; |
||||
23 | } |
||||
24 | |||||
25 | return $orderCode; |
||||
26 | } |
||||
27 | |||||
28 | /** |
||||
29 | * 生成出生日期码 |
||||
30 | * |
||||
31 | * @param $addressCode |
||||
0 ignored issues
–
show
|
|||||
32 | * @param $address |
||||
0 ignored issues
–
show
|
|||||
33 | * @param int|string $birthday 出生日期 |
||||
0 ignored issues
–
show
|
|||||
34 | * |
||||
35 | * @return string |
||||
36 | */ |
||||
37 | private function _generatorBirthdayCode($addressCode, $address, $birthday) |
||||
38 | { |
||||
39 | $start_year = '0001'; |
||||
40 | $end_year = '9999'; |
||||
41 | $year = $this->_datePad(substr($birthday, 0, 4), 'year'); |
||||
42 | $month = $this->_datePad(substr($birthday, 4, 2), 'month'); |
||||
43 | $day = $this->_datePad(substr($birthday, 6, 2), 'day'); |
||||
44 | |||||
45 | if ($year < 1800 || $year > date('Y')) { |
||||
46 | $year = $this->_datePad(mt_rand(1950, date('Y') - 1), 'year'); |
||||
47 | } |
||||
48 | |||||
49 | if (isset($this->_addressCodeTimeline[$addressCode])) { |
||||
50 | $timeline = $this->_addressCodeTimeline[$addressCode]; |
||||
51 | foreach ($timeline as $key => $val) { |
||||
52 | if ($val['address'] == $address) { |
||||
53 | $start_year = $val['start_year'] != '' ? $val['start_year'] : $start_year; |
||||
54 | $end_year = $val['end_year'] != '' ? $val['end_year'] : $end_year; |
||||
55 | } |
||||
56 | } |
||||
57 | } |
||||
58 | |||||
59 | if ($year < $start_year) { |
||||
60 | $year = $start_year; |
||||
61 | } |
||||
62 | if ($year > $end_year) { |
||||
63 | $year = $end_year; |
||||
64 | } |
||||
65 | |||||
66 | if ($month < 1 || $month > 12) { |
||||
67 | $month = $this->_datePad(mt_rand(1, 12), 'month'); |
||||
68 | } |
||||
69 | |||||
70 | if ($day < 1 || $day > 31) { |
||||
71 | $day = $this->_datePad(mt_rand(1, 28), 'day'); |
||||
72 | } |
||||
73 | |||||
74 | if (!checkdate((int) $month, (int) $day, (int) $year)) { |
||||
75 | $year = $this->_datePad(mt_rand(max($start_year, 1950), min($end_year, date('Y')) - 1), 'year'); |
||||
76 | $month = $this->_datePad(mt_rand(1, 12), 'month'); |
||||
77 | $day = $this->_datePad(mt_rand(1, 28), 'day'); |
||||
78 | } |
||||
79 | |||||
80 | return $year.$month.$day; |
||||
81 | } |
||||
82 | |||||
83 | /** |
||||
84 | * 生成地址码 |
||||
85 | * |
||||
86 | * @param string $address 地址(行政区全称) |
||||
87 | * |
||||
88 | * @return false|int|string |
||||
89 | */ |
||||
90 | private function _generatorAddressCode($address) |
||||
91 | { |
||||
92 | $addressCode = array_search($address, $this->_addressCodeList); |
||||
93 | $classification = $this->_addressCodeClassification($addressCode); |
||||
94 | switch ($classification) { |
||||
95 | case 'country': |
||||
0 ignored issues
–
show
|
|||||
96 | $pattern = '/\d{4}(?!00)[0-9]{2}$/'; |
||||
97 | $addressCode = $this->_getRandAddressCode($pattern); |
||||
98 | break; |
||||
99 | case 'province': |
||||
0 ignored issues
–
show
|
|||||
100 | $provinceCode = substr($addressCode, 0, 2); |
||||
101 | $pattern = '/^'.$provinceCode.'\d{2}(?!00)[0-9]{2}$/'; |
||||
102 | $addressCode = $this->_getRandAddressCode($pattern); |
||||
103 | break; |
||||
104 | case 'city': |
||||
0 ignored issues
–
show
|
|||||
105 | $cityCode = substr($addressCode, 0, 4); |
||||
106 | $pattern = '/^'.$cityCode.'(?!00)[0-9]{2}$/'; |
||||
107 | $addressCode = $this->_getRandAddressCode($pattern); |
||||
108 | break; |
||||
109 | } |
||||
110 | |||||
111 | return $addressCode; |
||||
112 | } |
||||
113 | |||||
114 | /** |
||||
115 | * 生成校验码 |
||||
116 | * 详细计算方法 @lint https://zh.wikipedia.org/wiki/中华人民共和国公民身份号码 |
||||
117 | * |
||||
118 | * @param string $body 身份证号 body 部分 |
||||
119 | * |
||||
120 | * @return string |
||||
121 | */ |
||||
122 | private function _generatorCheckBit($body) |
||||
123 | { |
||||
124 | // 位置加权 |
||||
125 | $posWeight = []; |
||||
126 | for ($i = 18; $i > 1; $i--) { |
||||
127 | $weight = (2 ** ($i - 1)) % 11; |
||||
128 | $posWeight[$i] = $weight; |
||||
129 | } |
||||
130 | |||||
131 | // 累身份证号 body 部分与位置加权的积 |
||||
132 | $bodySum = 0; |
||||
133 | $bodyArray = str_split($body); |
||||
134 | $count = count($bodyArray); |
||||
0 ignored issues
–
show
It seems like
$bodyArray can also be of type true ; however, parameter $value of count() does only seem to accept Countable|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
![]() |
|||||
135 | for ($j = 0; $j < $count; $j++) { |
||||
136 | $bodySum += ((int) $bodyArray[$j] * $posWeight[18 - $j]); |
||||
137 | } |
||||
138 | |||||
139 | // 生成校验码 |
||||
140 | $checkBit = (12 - ($bodySum % 11)) % 11; |
||||
141 | |||||
142 | return $checkBit == 10 ? 'X' : (string) $checkBit; |
||||
143 | } |
||||
144 | |||||
145 | /** |
||||
146 | * 地址码分类. |
||||
147 | * |
||||
148 | * @param $addressCode |
||||
0 ignored issues
–
show
|
|||||
149 | * |
||||
150 | * @return string |
||||
151 | */ |
||||
152 | private function _addressCodeClassification($addressCode) |
||||
153 | { |
||||
154 | if (!$addressCode) { |
||||
155 | // 全国 |
||||
156 | return 'country'; |
||||
157 | } |
||||
158 | if (substr($addressCode, 0, 1) == 8) { |
||||
159 | // 港澳台 |
||||
160 | return 'special'; |
||||
161 | } |
||||
162 | if (substr($addressCode, 2, 4) == '0000') { |
||||
163 | // 省级 |
||||
164 | return 'province'; |
||||
165 | } |
||||
166 | if (substr($addressCode, 4, 2) == '00') { |
||||
167 | // 市级 |
||||
168 | return 'city'; |
||||
169 | } |
||||
170 | // 县级 |
||||
171 | return 'district'; |
||||
172 | } |
||||
173 | |||||
174 | /** |
||||
175 | * 获取随机地址码. |
||||
176 | * |
||||
177 | * @param string $pattern 模式 |
||||
178 | * |
||||
179 | * @return string |
||||
180 | */ |
||||
181 | private function _getRandAddressCode($pattern) |
||||
182 | { |
||||
183 | $keys = array_keys($this->_addressCodeList); |
||||
184 | $result = preg_grep($pattern, $keys); |
||||
185 | |||||
186 | return $result[array_rand($result)]; |
||||
187 | } |
||||
188 | |||||
189 | /** |
||||
190 | * 日期补全. |
||||
191 | * |
||||
192 | * @param string|int $date 日期 |
||||
193 | * @param string $type 类型 |
||||
194 | * |
||||
195 | * @return string |
||||
196 | */ |
||||
197 | private function _datePad($date, $type = 'year') |
||||
198 | { |
||||
199 | $padLength = $type === 'year' ? 4 : 2; |
||||
200 | |||||
201 | return str_pad($date, $padLength, '0', STR_PAD_LEFT); |
||||
202 | } |
||||
203 | } |
||||
204 |