IdCard::passes()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5.0488

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 5
eloc 15
c 4
b 0
f 0
nc 5
nop 1
dl 0
loc 28
ccs 14
cts 16
cp 0.875
crap 5.0488
rs 9.4555
1
<?php
2
3
/*
4
 * This file is part of the godruoyi/laravel-idcard-validator.
5
 *
6
 * (c) Godruoyi <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled.
9
 */
10
11
namespace Godruoyi\LaravelIdCard;
12
13
class IdCard
14
{
15
    /**
16
     * 允许的地区码
17
     *
18
     * @var array
19
     */
20
    protected static $areaCodes = [
21
        11 => '北京',
22
        12 => '天津',
23
        13 => '河北',
24
        14 => '山西',
25
        15 => '内蒙古',
26
        21 => '辽宁',
27
        22 => '吉林',
28
        23 => '黑龙江',
29
        31 => '上海',
30
        32 => '江苏',
31
        33 => '浙江',
32
        34 => '安徽',
33
        35 => '福建',
34
        36 => '江西',
35
        37 => '山东',
36
        41 => '河南',
37
        42 => '湖北',
38
        43 => '湖南',
39
        44 => '广东',
40
        45 => '广西',
41
        46 => '海南',
42
        50 => '重庆',
43
        51 => '四川',
44
        52 => '贵州',
45
        53 => '云南',
46
        54 => '西藏',
47
        61 => '陕西',
48
        62 => '甘肃',
49
        63 => '青海',
50
        64 => '宁夏',
51
        65 => '新疆',
52
        81 => '香港',
53
        82 => '澳门',
54
        83 => '台湾',
55
    ];
56
57
    /**
58
     * 安全码
59
     *
60
     * @var array
61
     */
62
    protected static $securityCodes = [
63
        1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2,
64
    ];
65
66
    /**
67
     * Determine if the gieved idcard is passed.
68
     *
69
     * @param string $value
70
     *
71
     * @return bool
72
     */
73 2
    public static function passes($idcard)
74
    {
75 2
        if (!preg_match('/^'.self::resolveMatchRule().'$/', $idcard)) {
76 1
            return false;
77
        }
78
79 2
        $areaCode = substr($idcard, 0, 2);
80 2
        if (!isset(self::$areaCodes[$areaCode])) {
81
            return false;
82
        }
83
84 2
        $month = (int) substr($idcard, 10, 2);
85 2
        $day = (int) substr($idcard, 12, 2);
86 2
        $year = (int) substr($idcard, 6, 4);
87
88 2
        if (!checkdate($month, $day, $year)) {
89
            return false;
90
        }
91
92 2
        $sum = 0;
93
94 2
        for ($i = 17; $i > 0; --$i) {
95 2
            $s = pow(2, $i) % 11;
96
97 2
            $sum += $s * $idcard[17 - $i];
98
        }
99
100 2
        return (int) self::$securityCodes[$sum % 11] === (int) $idcard[17];
101
    }
102
103
    /**
104
     * Resolve IdCard Validate Rule.
105
     *
106
     * like '[1-6|8]{1}\d{5}[19|20]{2}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9xX]{1}'
107
     *
108
     * @return string
109
     */
110 3
    public static function resolveMatchRule()
111
    {
112 3
        $rule = '';
113
114 3
        foreach (['areacode', 'years', 'months', 'days', 'randoms', 'checkcode'] as $method) {
115 3
            $method = sprintf('resolveMatchRuleFor%s', ucfirst($method));
116 3
            $rule .= self::$method();
117
        }
118
119 3
        return $rule;
120
    }
121
122
    /**
123
     * 地址码规则:.
124
     *
125
     *     地址码长 6 位
126
     *     以数字 1-9 开头
127
     *     后 5 位为 0-9 的数字
128
     *
129
     * @return string
130
     */
131 4
    public static function resolveMatchRuleForAreacode()
132
    {
133 4
        return '[1-9]\d{5}';
134
    }
135
136
    /**
137
     * 年份码规则:.
138
     *
139
     *    年份码长 4 位
140
     *    以数字 18,19 或 20 开头,分表表示 18xx 19xx 20xx
141
     *    剩余两位为 0-9 的数字
142
     *
143
     * @return string
144
     */
145 4
    public static function resolveMatchRuleForYears()
146
    {
147 4
        return '(17|18|19|20|21)\d{2}';
148
    }
149
150
    /**
151
     * 月份码规则:.
152
     *
153
     *     月份码长 2 位
154
     *     第一位数字为 0,第二位数字为 1-9 即 01 02 等月份
155
     *
156
     *     或者 10 11 12 月份
157
     *
158
     * @return string
159
     */
160 4
    public static function resolveMatchRuleForMonths()
161
    {
162 4
        return '((0[1-9])|(10|11|12))';
163
    }
164
165
    /**
166
     * 日期码规则:.
167
     *
168
     *    日期码长2位
169
     *    第一位数字为0-2,第二位数字为1-9 即 01 22 11 等
170
     *    或者是10,20,30,31
171
     *
172
     * @return string
173
     */
174 4
    public static function resolveMatchRuleForDays()
175
    {
176 4
        return '(([0-2][1-9])|10|20|30|31)';
177
    }
178
179
    /**
180
     * 随机码规则:.
181
     *
182
     *     随机码长 3 位
183
     *     随机码是数字
184
     *
185
     * @return string
186
     */
187 4
    public static function resolveMatchRuleForRandoms()
188
    {
189 4
        return '\d{3}';
190
    }
191
192
    /**
193
     * 校验码规则:.
194
     *
195
     *    校验码长1位
196
     *    可以是数字,字母x或字母X
197
     *
198
     * @return string
199
     */
200 4
    public static function resolveMatchRuleForCheckcode()
201
    {
202 4
        return '[0-9xX]{1}';
203
    }
204
}
205