Completed
Push — master ( 30d3de...6bbfea )
by Xu
29:18 queued 23:02
created

IdCardValidator   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 147
rs 9.8
c 0
b 0
f 0
wmc 31

6 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 5 2
C getCheckCode18() 0 38 12
B validateIdCard() 0 20 6
A validateValue() 0 9 3
A validateAttribute() 0 9 3
B getPowerSum() 0 14 5
1
<?php
2
/**
3
 * @link http://www.tintsoft.com/
4
 * @copyright Copyright (c) 2012 TintSoft Technology Co. Ltd.
5
 * @license http://www.tintsoft.com/license/
6
 */
7
namespace yuncms\validators;
8
9
use Yii;
10
use yii\validators\Validator;
11
12
/**
13
 * Class IdCardValidator
14
 * [ 'id_card', 'yuncms\validators\IdCardValidator', 'message'=> '呀!身份证号码格式不正确,请重试!' ],
15
 * @package yuncms\validators
16
 */
17
class IdCardValidator extends Validator
18
{
19
    /**
20
     * 每位加权因子
21
     */
22
    public $power = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
23
24
    /**
25
     * 第18位校检码
26
     */
27
    public $verifyCode = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"];
28
29
    /**
30
     * @inheritdoc
31
     */
32
    public function init()
33
    {
34
        parent::init();
35
        if ($this->message === null) {
36
            $this->message = Yii::t('yuncms', '{attribute} Do not meet the rules.');
37
        }
38
    }
39
40
    /**
41
     * @inheritdoc
42
     */
43
    public function validateAttribute($model, $attribute)
44
    {
45
        $value = $model->$attribute;
46
        if (is_array($value)) {
47
            $this->addError($model, $attribute, $this->message);
48
            return;
49
        }
50
        if (!$this->validateIdCard($value)) {
51
            $this->addError($model, $attribute, $this->message);
52
        }
53
    }
54
55
    /**
56
     * @inheritdoc
57
     */
58
    protected function validateValue($value)
59
    {
60
        if (is_array($value)) {
61
            return [Yii::t('yii', '{attribute} is invalid.'), []];
62
        }
63
        if (!$this->validateIdCard($value)) {
64
            return [$this->message, []];
65
        } else {
66
            return null;
67
        }
68
    }
69
70
    /**
71
     * 验证18位身份编码是否合法
72
     *
73
     * @param int $idCard 身份编码
74
     * @return boolean 是否合法
75
     */
76
    public function validateIdCard($idCard)
77
    {
78
        if (strlen($idCard) == 18) {
79
            // 前17位
80
            $code17 = substr($idCard, 0, 17);
81
            // 第18位
82
            $code18 = substr($idCard, 17, 1);
83
            if (is_numeric($code17)) {
84
                $iArr = str_split($code17);
85
                if ($iArr != null) {
86
                    $iSum17 = $this->getPowerSum($iArr);
87
                    // 获取校验位
88
                    $val = $this->getCheckCode18($iSum17);
89
                    if (strlen($val) > 0 && $val == $code18) {
90
                        return true;
91
                    }
92
                }
93
            }
94
        }
95
        return false;
96
    }
97
98
    /**
99
     * 将power和值与11取模获得余数进行校验码判断
100
     *
101
     * @param int $iSum
102
     * @return string 校验位
103
     */
104
    private function getCheckCode18($iSum) {
105
        $sCode = "";
106
        switch ($iSum % 11) {
107
            case 10 :
108
                $sCode = "2";
109
                break;
110
            case 9 :
111
                $sCode = "3";
112
                break;
113
            case 8 :
114
                $sCode = "4";
115
                break;
116
            case 7 :
117
                $sCode = "5";
118
                break;
119
            case 6 :
120
                $sCode = "6";
121
                break;
122
            case 5 :
123
                $sCode = "7";
124
                break;
125
            case 4 :
126
                $sCode = "8";
127
                break;
128
            case 3 :
129
                $sCode = "9";
130
                break;
131
            case 2 :
132
                $sCode = "x";
133
                break;
134
            case 1 :
135
                $sCode = "0";
136
                break;
137
            case 0 :
138
                $sCode = "1";
139
                break;
140
        }
141
        return $sCode;
142
    }
143
144
    /**
145
     * 将身份证的每位和对应位的加权因子相乘之后,再得到和值
146
     *
147
     * @param array $iArr
148
     * @return int 身份证编码。
149
     */
150
    private function getPowerSum($iArr) {
151
        $iSum = 0;
152
        $powerLen = count ( $this->power );
153
        $arrLen = count ( $iArr );
154
        if ($powerLen == $arrLen) {
155
            for($i = 0; $i < $arrLen; $i ++) {
156
                for($j = 0; $j < $powerLen; $j ++) {
157
                    if ($i == $j) {
158
                        $iSum = $iSum + $iArr [$i] * $this->power [$j];
159
                    }
160
                }
161
            }
162
        }
163
        return $iSum;
164
    }
165
}