Skip to content

Commit

Permalink
Merge pull request #40 from fikus/determine-type
Browse files Browse the repository at this point in the history
Fixes for PhoneNumber type determination
  • Loading branch information
marmelroy committed Mar 27, 2016
2 parents af915c4 + 3207eea commit 5413101
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 27 deletions.
2 changes: 1 addition & 1 deletion PhoneNumberKit/PhoneNumber.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public struct PhoneNumber {
public var type: PhoneNumberType {
get {
let parser = PhoneNumberParser()
let type: PhoneNumberType = parser.checkNumberType(String(nationalNumber), countryCode: countryCode)
let type: PhoneNumberType = parser.checkNumberType(self)
return type
}
}
Expand Down
3 changes: 3 additions & 0 deletions PhoneNumberKit/PhoneNumberKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ public class PhoneNumberKit: NSObject {
return region.codeID
}
}
if number.leadingZero && parser.checkNumberType("0" + nationalNumber, metadata: region) != .Unknown {
return region.codeID
}
if parser.checkNumberType(nationalNumber, metadata: region) != .Unknown {
return region.codeID
}
Expand Down
51 changes: 30 additions & 21 deletions PhoneNumberKit/PhoneNumberParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,23 @@ class PhoneNumberParser {

/**
Check number type (e.g +33 612-345-678 to .Mobile).
- Parameter nationalNumber: National number string.
- Parameter countryCode: International country code (e.g 44 for the UK).
- Returns: Country code is UInt64.
- Parameter phoneNumber: The number to check
- Returns: The type of the number
*/
func checkNumberType(nationalNumber: String, countryCode: UInt64) -> PhoneNumberType {
guard let metadata = self.metadata.metadataPerCode[countryCode] else {
func checkNumberType(phoneNumber: PhoneNumber) -> PhoneNumberType {
guard let region = PhoneNumberKit().regionCodeForNumber(phoneNumber) else {
return .Unknown
}
guard let metadata = metadata.fetchMetadataForCountry(region) else {
return .Unknown
}
if phoneNumber.leadingZero {
let type = checkNumberType("0" + String(phoneNumber.nationalNumber), metadata: metadata)
if type != .Unknown {
return type
}
}
let nationalNumber = String(phoneNumber.nationalNumber)
return checkNumberType(nationalNumber, metadata: metadata)
}

Expand All @@ -131,19 +140,8 @@ class PhoneNumberParser {
if (regex.hasValue(generalNumberDesc.nationalNumberPattern) == false || isNumberMatchingDesc(nationalNumber, numberDesc: generalNumberDesc) == false) {
return .Unknown
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.fixedLine)) {
if metadata.fixedLine?.nationalNumberPattern == metadata.mobile?.nationalNumberPattern {
return .FixedOrMobile
}
else if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.mobile)) {
return .FixedOrMobile
}
else {
return .FixedLine
}
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.mobile)) {
return .Mobile
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.pager)) {
return .Pager
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.premiumRate)) {
return .PremiumRate
Expand All @@ -160,15 +158,26 @@ class PhoneNumberParser {
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.personalNumber)) {
return .PersonalNumber
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.pager)) {
return .Pager
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.uan)) {
return .UAN
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.voicemail)) {
return .Voicemail
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.fixedLine)) {
if metadata.fixedLine?.nationalNumberPattern == metadata.mobile?.nationalNumberPattern {
return .FixedOrMobile
}
else if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.mobile)) {
return .FixedOrMobile
}
else {
return .FixedLine
}
}
if (isNumberMatchingDesc(nationalNumber, numberDesc: metadata.mobile)) {
return .Mobile
}
return .Unknown
}

Expand Down
2 changes: 1 addition & 1 deletion PhoneNumberKit/RegularExpressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class RegularExpressions {
guard var pattern = pattern else {
return false
}
pattern = "^\(pattern)$"
pattern = "^(\(pattern))$"
return matchesExist(pattern, string: string)
}

Expand Down
76 changes: 72 additions & 4 deletions PhoneNumberKitTests/PhoneNumberKitParsingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,32 @@ class PhoneNumberKitParsingTests: XCTestCase {
let metaDataArray = PhoneNumberKit().metadata.items.filter{$0.codeID.characters.count == 2}
for metadata in metaDataArray {
let codeID = metadata.codeID
let metaDataDescriptions = [metadata.generalDesc, metadata.fixedLine, metadata.mobile, metadata.tollFree, metadata.premiumRate, metadata.sharedCost, metadata.voip, metadata.voicemail, metadata.pager, metadata.uan, metadata.emergency]
for desc in metaDataDescriptions {
if desc != nil {
if let exampleNumber = desc?.exampleNumber {
let metadataWithTypes: [(MetadataPhoneNumberDesc?, PhoneNumberType?)] = [
(metadata.generalDesc, nil),
(metadata.fixedLine, .FixedLine),
(metadata.mobile, .Mobile),
(metadata.tollFree, .TollFree),
(metadata.premiumRate, .PremiumRate),
(metadata.sharedCost, .SharedCost),
(metadata.voip, .VOIP),
(metadata.voicemail, .Voicemail),
(metadata.pager, .Pager),
(metadata.uan, .UAN),
(metadata.emergency, nil),
]
metadataWithTypes.forEach { record in
if let desc = record.0 {
if let exampleNumber = desc.exampleNumber {
do {
let phoneNumber = try PhoneNumber(rawNumber: exampleNumber, region: codeID)
XCTAssertNotNil(phoneNumber)
if let type = record.1 {
if phoneNumber.type == .FixedOrMobile {
XCTAssert(type == .FixedLine || type == .Mobile)
} else {
XCTAssertEqual(phoneNumber.type, type, "Expected type \(type) for number \(phoneNumber)")
}
}
} catch (let e) {
XCTFail("Failed to create PhoneNumber for \(exampleNumber): \(e)")
}
Expand All @@ -235,6 +254,55 @@ class PhoneNumberKitParsingTests: XCTestCase {
XCTAssertEqual(number.type, PhoneNumberType.TollFree)
}

func testBelizeTollFreeType() {
guard let number = try? PhoneNumber(rawNumber: "08001234123", region: "BZ") else {
XCTFail()
return
}
XCTAssertEqual(number.type, PhoneNumberType.TollFree)
}

func testItalyFixedLineType() {
guard let number = try? PhoneNumber(rawNumber: "0669812345", region: "IT") else {
XCTFail()
return
}
XCTAssertEqual(number.type, PhoneNumberType.FixedLine)
}

func testMaldivesPagerNumber() {
guard let number = try? PhoneNumber(rawNumber: "7812345", region: "MV") else {
XCTFail()
return
}
XCTAssertEqual(number.type, PhoneNumberType.Pager)
}

func testZimbabweVoipType() {
guard let number = try? PhoneNumber(rawNumber: "8686123456", region: "ZW") else {
XCTFail()
return
}
XCTAssertEqual(number.type, PhoneNumberType.VOIP)

}

func testAntiguaPagerNumberType() {
guard let number = try? PhoneNumber(rawNumber: "12684061234") else {
XCTFail()
return
}
XCTAssertEqual(number.type, PhoneNumberType.Pager)
}

func testFranceMobileNumberType() {
guard let number = try? PhoneNumber(rawNumber: "+33 612-345-678") else {
XCTFail()
return
}
XCTAssertEqual(number.type, PhoneNumberType.Mobile)
}

func testPerformanceSimple() {
let numberOfParses = 1000
let startTime = NSDate()
Expand Down

0 comments on commit 5413101

Please sign in to comment.