jxlwqq /
id-validator
| 1 | <?php |
||||
| 2 | |||||
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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 |