diff --git a/README.md b/README.md index d0185a3..2e36e83 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ $ go get -u github.com/x-validator/validator ### API列表 ```go -bool valid = validator.IsValidPhone("11011001111", false, []PhoneType{ AllType }) +bool valid = validator.IsValidPhone("11011001111", false, AllTypePhoneNumber) bool valid = validator.IsValidMoney("23.54", false) @@ -48,11 +48,11 @@ bool valid = validator.IsValidEmail("abcd@example.org", false) 可以选择验证哪些手机号,或者全部手机号,参考了[ChinaMobilePhoneNumberRegex](https://github.com/VincentSit/ChinaMobilePhoneNumberRegex)项目: -- **Basic**:仅基础运营商手机卡,11位手机卡-基础运营商,支持语音通话/短信/数据流量 -- **Virtual**:仅虚拟运营商号码,11位手机卡-虚拟运营商,支持语音通话/短信/数据流量 -- **NetOnly**:仅上网数据卡,11位上网卡,支持语音通话(部分)/短信/数据流量 -- **IotOnly**:仅物联网数据卡,13位物联网数据卡,支持数据流量 -- **AllType**:验证所有有效号码(手机卡 + 数据卡 + 上网卡) +- **BasicPhoneNumber**:仅基础运营商手机卡,11位手机卡-基础运营商,支持语音通话/短信/数据流量 +- **VirtualPhoneNumber**:仅虚拟运营商号码,11位手机卡-虚拟运营商,支持语音通话/短信/数据流量 +- **NetOnlyPhoneNumber**:仅上网数据卡,11位上网卡,支持语音通话(部分)/短信/数据流量 +- **IotOnlyPhoneNumber**:仅物联网数据卡,13位物联网数据卡,支持数据流量 +- **AllTypePhoneNumber**:验证所有有效号码(手机卡 + 数据卡 + 上网卡) ## 贡献 diff --git a/phone_test.go b/phone_test.go deleted file mode 100644 index 8f0a88f..0000000 --- a/phone_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// @Since 2024-03-24. -// @Author Fury, All rights Reserved. - -package validator - -import ( - "github.com/stretchr/testify/assert" - "testing" -) - -func TestIsValidPhone(t *testing.T) { - // test empty - pts := []PhoneType{Basic, Virtual, NetOnly, IotOnly, AllType} - for _, pt := range pts { - assert.True(t, IsValidPhone("", true, []PhoneType{pt})) - assert.False(t, IsValidPhone("", false, []PhoneType{pt})) - } - - // test phones - caseMap := map[string]map[PhoneType]bool{ - "18157610011": { // valid basic - Basic: true, - Virtual: false, - NetOnly: false, - IotOnly: false, - AllType: true, - }, - "16577810902": { // valid virtual - Basic: false, - Virtual: true, - NetOnly: false, - IotOnly: false, - AllType: true, - }, - "14577812563": { // valid net - Basic: false, - Virtual: false, - NetOnly: true, - IotOnly: false, - AllType: true, - }, - "1440775619012": { // valid iot - Basic: false, - Virtual: false, - NetOnly: false, - IotOnly: true, - AllType: true, - }, - "123456": { // all invalid - Basic: false, - Virtual: false, - NetOnly: false, - IotOnly: false, - AllType: false, - }, - "181778189012": { // all invalid - Basic: false, - Virtual: false, - NetOnly: false, - IotOnly: false, - AllType: false, - }, - "1817781890123": { // all invalid - Basic: false, - Virtual: false, - NetOnly: false, - IotOnly: false, - AllType: false, - }, - "181ab7781cd": { // all invalid - Basic: false, - Virtual: false, - NetOnly: false, - IotOnly: false, - AllType: false, - }, - } - for phone, kv := range caseMap { - for pt, expect := range kv { - assert.Equal(t, expect, IsValidPhone(phone, false, []PhoneType{pt})) - assert.Equal(t, expect, IsValidPhone(phone, true, []PhoneType{pt})) - } - } - -} diff --git a/phone.go b/phonenumber.go similarity index 59% rename from phone.go rename to phonenumber.go index 7a0d2cc..1a28996 100644 --- a/phone.go +++ b/phonenumber.go @@ -12,50 +12,50 @@ var netOnlyRegexp = regexp.MustCompile("^(?:\\+?86)?14[579]\\d{8}$") var iotOnlyRegexp = regexp.MustCompile("^(?:\\+?86)?14(?:[14]0|41|[68]\\d)\\d{9}$") var allTypeRegexp = regexp.MustCompile("^(?:\\+?86)?1(?:3\\d{3}|5[^4\\D]\\d{2}|8\\d{3}|7(?:[0-35-9]\\d{2}|4(?:0\\d|1[0-2]|9\\d))|9[0-35-9]\\d{2}|6[2567]\\d{2}|4(?:(?:10|4[01])\\d{3}|[68]\\d{4}|[579]\\d{2}))\\d{6}$") -type PhoneType int +type PhoneNumberType int const ( - // Basic 11位手机卡-基础运营商,支持语音通话/短信/数据流量 - Basic PhoneType = iota - // Virtual 11位手机卡-虚拟运营商,支持语音通话/短信/数据流量 - Virtual - // NetOnly 11位上网卡,支持语音通话(部分)/短信/数据流量 - NetOnly - // IotOnly 13位物联网数据卡,支持数据流量 - IotOnly - // AllType 包含以上4种 - AllType + // BasicPhoneNumber 11位手机卡-基础运营商,支持语音通话/短信/数据流量 + BasicPhoneNumber PhoneNumberType = iota + // VirtualPhoneNumber 11位手机卡-虚拟运营商,支持语音通话/短信/数据流量 + VirtualPhoneNumber + // NetOnlyPhoneNumber 11位上网卡,支持语音通话(部分)/短信/数据流量 + NetOnlyPhoneNumber + // IotOnlyPhoneNumber 13位物联网数据卡,支持数据流量 + IotOnlyPhoneNumber + // AllTypePhoneNumber 包含以上4种 + AllTypePhoneNumber ) -func getPhoneRegexp(phoneType PhoneType) *regexp.Regexp { +func getPhoneRegexp(phoneType PhoneNumberType) *regexp.Regexp { switch phoneType { - case Basic: + case BasicPhoneNumber: return basicRegexp - case Virtual: + case VirtualPhoneNumber: return virtualRegexp - case NetOnly: + case NetOnlyPhoneNumber: return netOnlyRegexp - case IotOnly: + case IotOnlyPhoneNumber: return iotOnlyRegexp default: // all type, 11或13位,支持所有号码 return allTypeRegexp } } -// IsValidPhone 手机号码 +// IsValidPhoneNumber 手机号码 // allowEmpty: return true if phone is nil or "" // Validate is the phone a valid phone number -func IsValidPhone(phone string, allowEmpty bool, types []PhoneType) bool { +func IsValidPhoneNumber(phone string, allowEmpty bool, types ...PhoneNumberType) bool { if value, ok := testNotBlank(phone); ok { if len(types) == 0 { - types = []PhoneType{Basic, Virtual, NetOnly} + types = []PhoneNumberType{BasicPhoneNumber, VirtualPhoneNumber, NetOnlyPhoneNumber} } for _, phoneType := range types { if getPhoneRegexp(phoneType).MatchString(value) { return true } - if phoneType == AllType { + if phoneType == AllTypePhoneNumber { break } } diff --git a/phonenumber_test.go b/phonenumber_test.go new file mode 100644 index 0000000..81c002e --- /dev/null +++ b/phonenumber_test.go @@ -0,0 +1,85 @@ +// @Since 2024-03-24. +// @Author Fury, All rights Reserved. + +package validator + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestIsValidPhone(t *testing.T) { + // test empty + pts := []PhoneNumberType{BasicPhoneNumber, VirtualPhoneNumber, NetOnlyPhoneNumber, IotOnlyPhoneNumber, AllTypePhoneNumber} + for _, pt := range pts { + assert.True(t, IsValidPhoneNumber("", true, []PhoneNumberType{pt})) + assert.False(t, IsValidPhoneNumber("", false, []PhoneNumberType{pt})) + } + + // test phones + caseMap := map[string]map[PhoneNumberType]bool{ + "18157610011": { // valid basic + BasicPhoneNumber: true, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: true, + }, + "16577810902": { // valid virtual + BasicPhoneNumber: false, + VirtualPhoneNumber: true, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: true, + }, + "14577812563": { // valid net + BasicPhoneNumber: false, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: true, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: true, + }, + "1440775619012": { // valid iot + BasicPhoneNumber: false, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: true, + AllTypePhoneNumber: true, + }, + "123456": { // all invalid + BasicPhoneNumber: false, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: false, + }, + "181778189012": { // all invalid + BasicPhoneNumber: false, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: false, + }, + "1817781890123": { // all invalid + BasicPhoneNumber: false, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: false, + }, + "181ab7781cd": { // all invalid + BasicPhoneNumber: false, + VirtualPhoneNumber: false, + NetOnlyPhoneNumber: false, + IotOnlyPhoneNumber: false, + AllTypePhoneNumber: false, + }, + } + for phone, kv := range caseMap { + for pt, expect := range kv { + assert.Equal(t, expect, IsValidPhoneNumber(phone, false, []PhoneNumberType{pt})) + assert.Equal(t, expect, IsValidPhoneNumber(phone, true, []PhoneNumberType{pt})) + } + } + +} diff --git a/tags.go b/tags.go new file mode 100644 index 0000000..34dfed3 --- /dev/null +++ b/tags.go @@ -0,0 +1,16 @@ +package validator + +type Fn func(value string, allowEmpty bool) bool + +// TagMaps tags map, when you want to add a new validation to the validator +// you can range this map to get the tag and valid function +var TagMaps = map[string]Fn{ + "email": IsValidEmail, + "http_url": IsValidHttpURL, + "id_card": IsValidIdCard, + "identifier": IsValidIdentifier, + "money": IsValidMoney, + "phone_number": func(value string, allowEmpty bool) bool { + return IsValidPhoneNumber(value, allowEmpty, AllTypePhoneNumber) + }, +}