Passed
Push — master ( d66128...ce6bd6 )
by jxlwqq
02:12
created

Generator::_generatorBirthdayCode()   C

Complexity

Conditions 15
Paths 128

Size

Total Lines 45
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 15
eloc 26
c 3
b 0
f 0
nc 128
nop 3
dl 0
loc 45
rs 5.6833

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 $addressCode
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
32
     * @param $address
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
33
     * @param int|string $birthday 出生日期
0 ignored issues
show
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
34
     *
35
     * @return string
36
     */
37
    private function _generatorBirthdayCode($addressCode, $address, $birthday)
38
    {
39
40
        $start_year = '0001';
41
        $end_year = '9999';
42
        $year = $this->_datePad(substr($birthday, 0, 4), 'year');
43
        $month = $this->_datePad(substr($birthday, 4, 2), 'month');
44
        $day = $this->_datePad(substr($birthday, 6, 2), 'day');
45
46
        if ($year < 1800 || $year > date('Y')) {
47
            $year = $this->_datePad(rand(1950, date('Y') - 1), 'year');
48
        }
49
50
        if (isset($this->_addressCodeTimeline[$addressCode])) {
51
            $timeline = $this->_addressCodeTimeline[$addressCode];
52
            foreach ($timeline as $key => $val) {
53
                if ($val['address'] == $address) {
54
                    $start_year = $val['start_year'] != '' ? $val['start_year'] : $start_year;
55
                    $end_year = $val['end_year'] != '' ? $val['end_year'] : $end_year;
56
                }
57
            }
58
        }
59
60
        if ($year < $start_year) {
61
            $year = $start_year;
62
        }
63
        if ($year > $end_year) {
64
            $year = $end_year;
65
        }
66
67
        if ($month < 1 || $month > 12) {
68
            $month = $this->_datePad(rand(1, 12), 'month');
69
        }
70
71
        if ($day < 1 || $day > 31) {
72
            $day = $this->_datePad(rand(1, 28), 'day');
73
        }
74
75
        if (!checkdate((int) $month, (int) $day, (int) $year)) {
76
            $year = $this->_datePad(rand(max($start_year, 1950), min($end_year, date('Y')) - 1), 'year');
77
            $month = $this->_datePad(rand(1, 12), 'month');
78
            $day = $this->_datePad(rand(1, 28), 'day');
79
        }
80
81
        return $year.$month.$day;
82
    }
83
84
    /**
85
     * 生成地址码
86
     *
87
     * @param string $address 地址(行政区全称)
88
     *
89
     * @return false|int|string
90
     */
91
    private function _generatorAddressCode($address)
92
    {
93
        $addressCode = array_search($address, $this->_addressCodeList);
94
        $classification = $this->_addressCodeClassification($addressCode);
95
        switch ($classification) {
96
            case 'country':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
97
                $pattern = '/\d{4}(?!00)[0-9]{2}$/';
98
                $addressCode = $this->_getRandAddressCode($pattern);
99
                break;
100
            case 'province':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
101
                $provinceCode = substr($addressCode, 0, 2);
102
                $pattern = '/^'.$provinceCode.'\d{2}(?!00)[0-9]{2}$/';
103
                $addressCode = $this->_getRandAddressCode($pattern);
104
                break;
105
            case 'city':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
106
                $cityCode = substr($addressCode, 0, 4);
107
                $pattern = '/^'.$cityCode.'(?!00)[0-9]{2}$/';
108
                $addressCode = $this->_getRandAddressCode($pattern);
109
                break;
110
        }
111
112
        return $addressCode;
113
    }
114
115
    /**
116
     * 生成校验码
117
     * 详细计算方法 @lint https://zh.wikipedia.org/wiki/中华人民共和国公民身份号码
118
     *
119
     * @param string $body 身份证号 body 部分
120
     *
121
     * @return string
122
     */
123
    private function _generatorCheckBit($body)
124
    {
125
        // 位置加权
126
        $posWeight = [];
127
        for ($i = 18; $i > 1; $i--) {
128
            $weight = pow(2, $i - 1) % 11;
129
            $posWeight[$i] = $weight;
130
        }
131
132
        // 累身份证号 body 部分与位置加权的积
133
        $bodySum = 0;
134
        $bodyArray = str_split($body);
135
        $count = count($bodyArray);
0 ignored issues
show
Bug introduced by
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 ignore-type  annotation

135
        $count = count(/** @scrutinizer ignore-type */ $bodyArray);
Loading history...
136
        for ($j = 0; $j < $count; $j++) {
137
            $bodySum += (intval($bodyArray[$j]) * $posWeight[18 - $j]);
138
        }
139
140
        // 生成校验码
141
        $checkBit = (12 - ($bodySum % 11)) % 11;
142
143
        return $checkBit == 10 ? 'X' : (string) $checkBit;
144
    }
145
146
    /**
147
     * 地址码分类.
148
     *
149
     * @param $addressCode
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
150
     *
151
     * @return string
152
     */
153
    private function _addressCodeClassification($addressCode)
154
    {
155
        if (!$addressCode) {
156
            // 全国
157
            return 'country';
158
        }
159
        if (substr($addressCode, 0, 1) == 8) {
160
            // 港澳台
161
            return 'special';
162
        }
163
        if (substr($addressCode, 2, 4) == '0000') {
164
            // 省级
165
            return 'province';
166
        }
167
        if (substr($addressCode, 4, 2) == '00') {
168
            // 市级
169
            return 'city';
170
        }
171
        // 县级
172
        return 'district';
173
    }
174
175
    /**
176
     * 获取随机地址码.
177
     *
178
     * @param string $pattern 模式
179
     *
180
     * @return string
181
     */
182
    private function _getRandAddressCode($pattern)
183
    {
184
        $keys = array_keys($this->_addressCodeList);
185
        $result = preg_grep($pattern, $keys);
186
187
        return $result[array_rand($result)];
188
    }
189
190
    /**
191
     * 日期补全.
192
     *
193
     * @param string|int $date 日期
194
     * @param string     $type 类型
195
     *
196
     * @return string
197
     */
198
    private function _datePad($date, $type = 'year')
199
    {
200
        $padLength = $type == 'year' ? 4 : 2;
201
        $newDate = str_pad($date, $padLength, '0', STR_PAD_LEFT);
202
203
        return $newDate;
204
    }
205
}
206