Generator::_generatorBirthdayCode()   C
last analyzed

Complexity

Conditions 15
Paths 128

Size

Total Lines 44
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 44
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 = 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
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
        $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
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
96
                $pattern = '/\d{4}(?!00)[0-9]{2}$/';
97
                $addressCode = $this->_getRandAddressCode($pattern);
98
                break;
99
            case 'province':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
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
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
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
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

134
        $count = count(/** @scrutinizer ignore-type */ $bodyArray);
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
Coding Style introduced by
Missing parameter comment
Loading history...
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