Passed
Push — master ( 6bd3b2...bd9248 )
by jxlwqq
02:21 queued 28s
created

Generator::_datePad()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
namespace Jxlwqq\IdValidator;
4
5
/**
6
 * Trait Generator.
7
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
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 = 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 int|string $birthday 出生日期
32
     *
33
     * @return string
34
     */
35
    public function _generatorBirthdayCode($birthday)
0 ignored issues
show
Coding Style introduced by
Public method name "Generator::_generatorBirthdayCode" must not be prefixed with an underscore
Loading history...
36
    {
37
        $year = $this->_datePad(substr($birthday, 0, 4), 'year');
38
        $month = $this->_datePad(substr($birthday, 4, 2), 'month');
39
        $day = $this->_datePad(substr($birthday, 6, 2), 'day');
40
41
        if ($year < 1800 || $year > date('Y')) {
42
            $year = $this->_datePad(rand(1950, date('Y') - 1), 'year');
43
        }
44
45
        if ($month < 1 || $month > 12) {
46
            $month = $this->_datePad(rand(1, 12), 'month');
47
        }
48
49
        if ($day < 1 || $day > 31) {
50
            $day = $this->_datePad(rand(1, 28), 'day');
51
        }
52
53
        if (!checkdate($month, $day, $year)) {
0 ignored issues
show
Bug introduced by
$year of type string is incompatible with the type integer expected by parameter $year of checkdate(). ( Ignorable by Annotation )

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

53
        if (!checkdate($month, $day, /** @scrutinizer ignore-type */ $year)) {
Loading history...
Bug introduced by
$month of type string is incompatible with the type integer expected by parameter $month of checkdate(). ( Ignorable by Annotation )

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

53
        if (!checkdate(/** @scrutinizer ignore-type */ $month, $day, $year)) {
Loading history...
Bug introduced by
$day of type string is incompatible with the type integer expected by parameter $day of checkdate(). ( Ignorable by Annotation )

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

53
        if (!checkdate($month, /** @scrutinizer ignore-type */ $day, $year)) {
Loading history...
54
            $year = $this->_datePad(rand(1950, date('Y') - 1), 'year');
55
            $month = $this->_datePad(rand(1, 12), 'month');
56
            $day = $this->_datePad(rand(1, 28), 'day');
57
        }
58
59
        return $year.$month.$day;
60
    }
61
62
    /**
63
     * 生成地址码
64
     *
65
     * @param string $address 地址(行政区全称)
66
     *
67
     * @return false|int|string
68
     */
69
    private function _generatorAddressCode($address)
70
    {
71
        $addressCode = array_search($address, $this->_addressCodeList);
72
        $classification = $this->_addressCodeClassification($addressCode);
73
        switch ($classification) {
74
            case 'country':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
75
                $pattern = '/\d{4}(?!00)[0-9]{2}$/';
76
                $addressCode = $this->_getRandAddressCode($pattern);
77
                break;
78
            case 'province':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
79
                $provinceCode = substr($addressCode, 0, 2);
0 ignored issues
show
Bug introduced by
It seems like $addressCode can also be of type false; however, parameter $string of substr() does only seem to accept string, 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

79
                $provinceCode = substr(/** @scrutinizer ignore-type */ $addressCode, 0, 2);
Loading history...
80
                $pattern = '/^'.$provinceCode.'\d{2}(?!00)[0-9]{2}$/';
81
                $addressCode = $this->_getRandAddressCode($pattern);
82
                break;
83
            case 'city':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
84
                $cityCode = substr($addressCode, 0, 4);
85
                $pattern = '/^'.$cityCode.'(?!00)[0-9]{2}$/';
86
                $addressCode = $this->_getRandAddressCode($pattern);
87
                break;
88
        }
89
90
        return $addressCode;
91
    }
92
93
    /**
94
     * 生成校验码
95
     * 详细计算方法 @lint https://zh.wikipedia.org/wiki/中华人民共和国公民身份号码
96
     *
97
     * @param string $body 身份证号 body 部分
98
     *
99
     * @return int|string
100
     */
101
    private function _generatorCheckBit($body)
102
    {
103
        // 位置加权
104
        $posWeight = [];
105
        for ($i = 18; $i > 1; $i--) {
106
            $weight = pow(2, $i - 1) % 11;
107
            $posWeight[$i] = $weight;
108
        }
109
110
        // 累身份证号 body 部分与位置加权的积
111
        $bodySum = 0;
112
        $bodyArray = str_split($body);
113
        $count = count($bodyArray);
114
        for ($j = 0; $j < $count; $j++) {
115
            $bodySum += (intval($bodyArray[$j]) * $posWeight[18 - $j]);
116
        }
117
118
        // 生成校验码
119
        $checkBit = (12 - ($bodySum % 11)) % 11;
120
121
        return $checkBit == 10 ? 'X' : $checkBit;
122
    }
123
124
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $addressCode should have a doc-comment as per coding-style.
Loading history...
125
     * 地址码分类.
126
     *
127
     * @param $addressCode
0 ignored issues
show
Coding Style Documentation introduced by
Missing parameter name
Loading history...
128
     *
129
     * @return string
130
     */
131
    private function _addressCodeClassification($addressCode)
132
    {
133
        if (!$addressCode) {
134
            // 全国
135
            return 'country';
136
        }
137
        if (substr($addressCode, 0, 1) == 8) {
138
            // 港澳台
139
            return 'special';
140
        }
141
        if (substr($addressCode, 2, 4) == '0000') {
142
            // 省级
143
            return 'province';
144
        }
145
        if (substr($addressCode, 4, 2) == '00') {
146
            // 市级
147
            return 'city';
148
        }
149
        // 县级
150
        return 'district';
151
    }
152
153
    /**
154
     * 获取随机地址码.
155
     *
156
     * @param string $pattern 模式
157
     *
158
     * @return string
159
     */
160
    private function _getRandAddressCode($pattern)
161
    {
162
        $keys = array_keys($this->_addressCodeList);
163
        $result = preg_grep($pattern, $keys);
164
165
        return $result[array_rand($result)];
166
    }
167
168
    /**
169
     * 日期补全.
170
     *
171
     * @param string|int $date 日期
172
     * @param string     $type 类型
173
     *
174
     * @return string
175
     */
176
    private function _datePad($date, $type = 'year')
177
    {
178
        $padLength = $type == 'year' ? 4 : 2;
179
        $newDate = str_pad($date, $padLength, '0', STR_PAD_LEFT);
180
181
        return $newDate;
182
    }
183
}
184