phony 1.6.5 → 1.6.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/phony.rb CHANGED
@@ -12,6 +12,8 @@ require File.expand_path '../phony/national_splitters/default', __FILE__
12
12
  require File.expand_path '../phony/national_code', __FILE__
13
13
  require File.expand_path '../phony/country', __FILE__
14
14
  require File.expand_path '../phony/country_codes', __FILE__
15
+ require File.expand_path '../phony/validator', __FILE__
16
+ require File.expand_path '../phony/validators', __FILE__
15
17
  require File.expand_path '../phony/dsl', __FILE__
16
18
 
17
19
  # Countries.
@@ -37,7 +39,8 @@ module Phony
37
39
 
38
40
  # Phony uses a single country codes instance.
39
41
  #
40
- @codes = CountryCodes.instance
42
+ @codes = CountryCodes.instance
43
+ @validator = Validators.instance
41
44
 
42
45
  class << self
43
46
 
@@ -74,6 +77,16 @@ module Phony
74
77
  end
75
78
  alias formatted format
76
79
  alias formatted! format!
80
+
81
+ # Makes a plausibility check.
82
+ #
83
+ # If it returns false, it is not plausible.
84
+ # If it returns true, it is unclear whether it is plausible,
85
+ # leaning towards being plausible.
86
+ #
87
+ def plausible? number, hints = {}
88
+ @validator.plausible? number, hints
89
+ end
77
90
 
78
91
  # def service? number
79
92
  # @codes.service? number.dup
@@ -27,7 +27,9 @@ Phony.define do
27
27
 
28
28
  # USA, Canada, etc.
29
29
  #
30
- country '1', fixed(3) >> split(3,4)
30
+ country '1',
31
+ fixed(3) >> split(3,4),
32
+ invalid_ndcs(/911/)
31
33
 
32
34
  # Kazakhstan (Republic of) & Russian Federation.
33
35
  #
@@ -64,31 +66,33 @@ Phony.define do
64
66
 
65
67
  # Spain.
66
68
  #
67
- country '34', fixed(2) >> split(3,4)
69
+ country '34',
70
+ fixed(2) >> split(3,4)
68
71
 
69
72
  # Hungary.
70
73
  #
71
74
  # TODO Mobile.
72
75
  #
73
- country '36', one_of('104','105','107','112') >> split(3,3) | # Service
74
- one_of('1') >> split(3,4) | # Budapest
75
- fixed(2) >> split(3,4) # 2-digit NDCs
76
+ country '36',
77
+ one_of('104','105','107','112') >> split(3,3) | # Service
78
+ one_of('1') >> split(3,4) | # Budapest
79
+ fixed(2) >> split(3,4) # 2-digit NDCs
76
80
 
77
81
  # country '39' # Italy, see special file.
78
82
 
79
83
  # Romania.
80
84
  #
81
- country '40', match(/^(112|800|90[036])\d+$/) >> split(3,3) | # Service
82
- match(/^(7[1-8])\d+$/) >> split(3,4) | # Mobile
83
- one_of('21', '31') >> split(3,4) | # Bucureşti
84
- fixed(3) >> split(3,4) # 3-digit NDCs
85
+ country '40',
86
+ match(/^(112|800|90[036])\d+$/) >> split(3,3) | # Service
87
+ match(/^(7[1-8])\d+$/) >> split(3,4) | # Mobile
88
+ one_of('21', '31') >> split(3,4) | # Bucureşti
89
+ fixed(3) >> split(3,4) # 3-digit NDCs
85
90
 
86
91
  # Switzerland.
87
92
  #
88
- # :service => %w{800 840 842 844 848}, :mobile => %w{74 76 77 78 79}
89
- swiss_service_regex = /^(800|840|842|844|848)\d+$/
90
- country '41', match(swiss_service_regex) >> split(3,3) |
91
- fixed(2) >> split(3,2,2)
93
+ country '41',
94
+ match(/^(8(00|40|42|44|48))\d+$/) >> split(3,3) |
95
+ fixed(2) >> split(3,2,2)
92
96
 
93
97
 
94
98
  # country '43' # Austria, see special file.
@@ -96,61 +100,71 @@ Phony.define do
96
100
 
97
101
  # Denmark.
98
102
  #
99
- country '45', none >> split(2,2,2,2)
103
+ country '45',
104
+ none >> split(2,2,2,2)
100
105
 
101
106
  # country '46' # Sweden, see special file.
102
107
 
103
108
  # Norway.
104
109
  #
105
- country '47', none >> matched_split(/^[1].*$/ => [3], /^[489].*$/ => [3,2,3], :fallback => [2,2,2,2])
110
+ country '47',
111
+ none >> matched_split(/^[1].*$/ => [3],
112
+ /^[489].*$/ => [3,2,3],
113
+ :fallback => [2,2,2,2])
106
114
 
107
115
  # Poland (Republic of)
108
116
  # Although the NDCs are 2 digits, the representation is 3 digits.
109
117
  # Note: http://wapedia.mobi/en/Telephone_numbers_in_Poland, mobile not yet correct
110
118
  #
111
- country '48', fixed(3) >> split(3,3) # Poland
119
+ country '48',
120
+ fixed(3) >> split(3,3) # Poland
112
121
 
113
122
  # country '49' # Germany, see special file.
114
123
 
115
124
  # Peru.
116
125
  #
117
- country '51', one_of('103', '105') >> split(3,3) | # Service.
118
- one_of('1', '9') >> split(4,4) | # Lima and mobile.
119
- fixed(2) >> split(4,4) # 2-digit NDCs.
126
+ country '51',
127
+ one_of('103', '105') >> split(3,3) | # Service.
128
+ one_of('1', '9') >> split(4,4) | # Lima and mobile.
129
+ fixed(2) >> split(4,4) # 2-digit NDCs.
120
130
 
121
131
  # Mexico.
122
132
  #
123
- country '52', match(/^(0\d{2})\d+$/) >> split(2,2,2,2) |
124
- match(/^(33|55|81)\d+$/) >> split(2,2,2,2) |
125
- match(/^(\d{3})\d+$/) >> split(3,2,2)
133
+ country '52',
134
+ match(/^(0\d{2})\d+$/) >> split(2,2,2,2) |
135
+ match(/^(33|55|81)\d+$/) >> split(2,2,2,2) |
136
+ match(/^(\d{3})\d+$/) >> split(3,2,2)
126
137
 
127
138
  # Cuba.
128
139
  #
129
- country '53', match(/^(5\d{3})\d+$/) >> split(4) | # Mobile
130
- match(/^(7|21|22|23|4[1-8]|3[1-3])/) >> split(7) | # Short NDCs
131
- fixed(3) >> split(7) # 3-digit NDCs
140
+ country '53',
141
+ match(/^(5\d{3})\d+$/) >> split(4) | # Mobile
142
+ match(/^(7|21|22|23|4[1-8]|3[1-3])/) >> split(7) | # Short NDCs
143
+ fixed(3) >> split(7) # 3-digit NDCs
132
144
 
133
145
  # Argentine Republic.
134
146
  #
135
- country '54', one_of('11', '911') >> split(4,4) | # Fixed & Mobile
136
- match(/^(22[0137]|237|26[14]|29[179]|34[1235]|35[138]|38[1578])/) >> split(3,4) | # Fixed
137
- match(/^(922[0137]|9237|926[14]|929[179]|934[1235]|935[138]|938[1578])/) >> split(3,4) | # Mobile
138
- match(/^(9\d{4})/) >> split(2,4) | # Mobile
139
- fixed(4) >> split(2,4) # Fixed
147
+ country '54',
148
+ one_of('11', '911') >> split(4,4) | # Fixed & Mobile
149
+ match(/^(22[0137]|237|26[14]|29[179]|34[1235]|35[138]|38[1578])/) >> split(3,4) | # Fixed
150
+ match(/^(922[0137]|9237|926[14]|929[179]|934[1235]|935[138]|938[1578])/) >> split(3,4) | # Mobile
151
+ match(/^(9\d{4})/) >> split(2,4) | # Mobile
152
+ fixed(4) >> split(2,4) # Fixed
140
153
 
141
154
  # Brazil (Federative Republic of).
155
+ # http://en.wikipedia.org/wiki/Telephone_numbers_in_Brazil
142
156
  #
143
157
  brazilian_service = /^(100|128|190|191|192|193|194|197|198|199)\d+$/
144
- country '55', match(brazilian_service) >> split(3,3) | # Service.
145
- fixed(2) >> split(4,4) # NDCs
146
- # :service? => brazilian_service, :mobile? => ?
147
- # http://en.wikipedia.org/wiki/Telephone_numbers_in_Brazil
158
+ country '55',
159
+ match(brazilian_service) >> split(3,3) | # Service.
160
+ fixed(2) >> split(4,4) # NDCs
148
161
 
149
162
  # Chile.
150
163
  #
151
- country '56', match(/^(13[0-79]|14[79])\d+$/) >> split(3,3) | # Service
152
- one_of('2', '9') >> split(8) | # Santiago, Mobile
153
- fixed(2) >> split(8) # 2-digit NDCs
164
+ country '56',
165
+ match(/^(13[0-79]|14[79])\d+$/) >> split(3,3) | # Service
166
+ one_of('2', '9') >> split(8) | # Santiago, Mobile
167
+ fixed(2) >> split(8) # 2-digit NDCs
154
168
 
155
169
  # TODO Colombia.
156
170
  #
@@ -158,14 +172,17 @@ Phony.define do
158
172
 
159
173
  # Venezuela (Bolivarian Republic of)
160
174
  #
161
- country '58', fixed(3) >> split(7)
175
+ country '58',
176
+ fixed(3) >> split(7)
162
177
 
163
178
  # country '60' # Malaysia, see special file.
164
179
 
165
180
  # Australia.
166
181
  #
167
- country '61', match(/^(4\d\d)\d+$/) >> split(3,3) | # Mobile
168
- fixed(1) >> split(4,4) # Rest
182
+ country '61',
183
+ match(/^(4\d\d)\d+$/) >> split(3,3) | # Mobile
184
+ fixed(1) >> split(4,4) # Rest
185
+
169
186
  country '62', todo # TODO Indonesia (Republic of)
170
187
  country '63', todo # TODO Philippines (Republic of the)
171
188
 
@@ -173,16 +190,19 @@ Phony.define do
173
190
  #
174
191
  # TODO Mobile?
175
192
  #
176
- country '64', fixed(1) >> split(3,4)
193
+ country '64',
194
+ fixed(1) >> split(3,4)
177
195
 
178
196
  # Singapore (Republic of).
179
197
  #
180
- country '65', none >> split(4,4) # TODO Short Codes.
198
+ country '65',
199
+ none >> split(4,4) # TODO Short Codes.
181
200
 
182
201
  # Thailand.
183
202
  #
184
- country '66', one_of('2') >> split(3,4) | # Bangkok
185
- fixed(2) >> split(3,3) # Rest
203
+ country '66',
204
+ one_of('2') >> split(3,4) | # Bangkok
205
+ fixed(2) >> split(3,3) # Rest
186
206
 
187
207
  country '81', todo # TODO Japan
188
208
 
@@ -194,7 +214,8 @@ Phony.define do
194
214
 
195
215
  # Turkey.
196
216
  #
197
- country '90', fixed(3) >> split(3,4) # Wiki says 7, but the examples say 3, 4.
217
+ country '90',
218
+ fixed(3) >> split(3,4) # Wiki says 7, but the examples say 3, 4.
198
219
 
199
220
  country '91', todo # TODO India (Republic of)
200
221
  country '92', todo # TODO Pakistan (Islamic Republic of), http://en.wikipedia.org/wiki/Telephone_numbers_in_Pakistan, NDC 2-5
@@ -264,11 +285,20 @@ Phony.define do
264
285
  country '252', todo # Somali Democratic Republic
265
286
  country '253', todo # Djibouti
266
287
  country '254', fixed(2) >> split(7) # Kenya
267
- country '255', match(/^([89]\d\d)/) >> split(3,3) | # Special/Premium. Tanzania
268
- one_of('112', '118') >> split(3,3) | # Short Codes.
269
- fixed(2) >> split(3,4) # Geographic.
270
- country '256', match(/^(46[45]|4[78]\d)/) >> split(6) | # Geo 1. Uganda
271
- fixed(2) >> split(7) # Geo 2.
288
+
289
+ # Tanzania.
290
+ #
291
+ country '255',
292
+ match(/^([89]\d\d)/) >> split(3,3) | # Special/Premium.
293
+ one_of('112', '118') >> split(3,3) | # Short Codes.
294
+ fixed(2) >> split(3,4) # Geographic.
295
+
296
+ # Uganda.
297
+ #
298
+ country '256',
299
+ match(/^(46[45]|4[78]\d)/) >> split(6) | # Geo 1.
300
+ fixed(2) >> split(7) # Geo 2.
301
+
272
302
  country '257', todo # Burundi
273
303
  country '258', todo # Mozambique
274
304
  country '259', todo # -
@@ -310,10 +340,11 @@ Phony.define do
310
340
 
311
341
  # Portugal.
312
342
  #
313
- country '351', one_of('700', '800') >> split(3,3) | # Service.
314
- match(/^(9\d)\d+$/) >> split(3,4) | # Mobile.
315
- one_of('21', '22') >> split(3,4) | # Lisboa & Porto
316
- fixed(3) >> split(3,4) # 3-digit NDCs
343
+ country '351',
344
+ one_of('700', '800') >> split(3,3) | # Service.
345
+ match(/^(9\d)\d+$/) >> split(3,4) | # Mobile.
346
+ one_of('21', '22') >> split(3,4) | # Lisboa & Porto
347
+ fixed(3) >> split(3,4) # 3-digit NDCs
317
348
 
318
349
  country '352', todo # Luxembourg
319
350
 
@@ -326,19 +357,25 @@ Phony.define do
326
357
 
327
358
  # Finland.
328
359
  #
329
- country '358', match(/^([6-8]00)\d+$/) >> split(3,3) | # Service
330
- match(/^(4\d|50)\d+$/) >> split(3,2,2) | # Mobile
331
- one_of('2','3','5','6','8','9') >> split(3,3) | # Short NDCs
332
- fixed(2) >> split(3,3) # 2-digit NDCs
333
- country '359', fixed(2) >> split(3,2,2) # Bulgaria
360
+ country '358',
361
+ match(/^([6-8]00)\d+$/) >> split(3,3) | # Service
362
+ match(/^(4\d|50)\d+$/) >> split(3,2,2) | # Mobile
363
+ one_of('2','3','5','6','8','9') >> split(3,3) | # Short NDCs
364
+ fixed(2) >> split(3,3) # 2-digit NDCs
365
+
366
+ # Bulgaria.
367
+ #
368
+ country '359',
369
+ fixed(2) >> split(3,2,2) # Bulgaria
334
370
 
335
371
  # Lithuania.
336
372
  #
337
- country '370', one_of('700', '800') >> split(2,3) | # Service
338
- match(/^(6\d\d)\d+$/) >> split(2,3) | # Mobile
339
- one_of('5') >> split(3,2,2) | # Vilnius
340
- one_of('37','41') >> split(2,2,2) | # Kaunas, Šiauliai
341
- fixed(3) >> split(1,2,2) # 3-digit NDCs.
373
+ country '370',
374
+ one_of('700', '800') >> split(2,3) | # Service
375
+ match(/^(6\d\d)\d+$/) >> split(2,3) | # Mobile
376
+ one_of('5') >> split(3,2,2) | # Vilnius
377
+ one_of('37','41') >> split(2,2,2) | # Kaunas, Šiauliai
378
+ fixed(3) >> split(1,2,2) # 3-digit NDCs.
342
379
 
343
380
  country '371', todo # Latvia
344
381
  country '372', todo # Estonia
@@ -6,7 +6,7 @@ module Phony
6
6
  #
7
7
  class CountryCodes
8
8
 
9
- attr_reader :mapping
9
+ attr_reader :splitter_mapping
10
10
  attr_accessor :international_absolute_format, :international_relative_format, :national_format
11
11
 
12
12
  def initialize
@@ -22,11 +22,14 @@ module Phony
22
22
  @instance ||= new
23
23
  end
24
24
 
25
- @@normalizing_pattern = /^0+|\D/
26
- def normalize number
25
+ @@basic_normalizing_pattern = /^0+|\D/
26
+ def clean number
27
27
  # Remove non-digit chars.
28
28
  #
29
- number.gsub! @@normalizing_pattern, EMPTY_STRING
29
+ number.gsub! @@basic_normalizing_pattern, EMPTY_STRING
30
+ end
31
+ def normalize number
32
+ clean number
30
33
  national_handler, cc, rest = split_cc number
31
34
  @normalize_format % [cc, national_handler.normalize(rest)]
32
35
  end
@@ -102,7 +105,7 @@ module Phony
102
105
  presumed_cc = ''
103
106
  1.upto(3) do |i|
104
107
  presumed_cc << rest.slice!(0..0)
105
- national_code_handler = mapping[i][presumed_cc]
108
+ national_code_handler = splitter_mapping[i][presumed_cc]
106
109
  return [national_code_handler, presumed_cc, rest] if national_code_handler
107
110
  end
108
111
  # This line is never reached as CCs are in prefix code.
@@ -121,9 +124,9 @@ module Phony
121
124
  country_code = country_code.to_s
122
125
  optimized_country_code_access = country_code.size
123
126
 
124
- @mapping ||= {}
125
- @mapping[optimized_country_code_access] ||= {}
126
- @mapping[optimized_country_code_access][country_code] = country
127
+ @splitter_mapping ||= {}
128
+ @splitter_mapping[optimized_country_code_access] ||= {}
129
+ @splitter_mapping[optimized_country_code_access][country_code] = country
127
130
  end
128
131
 
129
132
  end
data/lib/phony/dsl.rb CHANGED
@@ -46,8 +46,9 @@ module Phony
46
46
 
47
47
  #
48
48
  #
49
- def country country_code, country
49
+ def country country_code, country, validator = nil
50
50
  Phony::CountryCodes.instance.add country_code, country
51
+ Phony::Validators.instance.add country_code, validator if validator
51
52
  end
52
53
 
53
54
  # National matcher & splitters.
@@ -89,6 +90,12 @@ module Phony
89
90
  def matched_split options = {}
90
91
  Phony::LocalSplitters::Regex.instance_for options
91
92
  end
93
+
94
+ # Validators
95
+ #
96
+ def invalid_ndcs ndc
97
+ Validator.new.ndc_check ndc
98
+ end
92
99
 
93
100
  end
94
101
 
@@ -0,0 +1,26 @@
1
+ module Phony
2
+
3
+ class Validator
4
+
5
+ attr_reader :ndc_checks
6
+
7
+ def initialize
8
+ @ndc_checks = []
9
+ end
10
+
11
+ def plausible? ndc, rest
12
+ ndc_checks && ndc_checks.each do |ndc_check|
13
+ return false if ndc_check === ndc
14
+ end
15
+
16
+ true
17
+ end
18
+
19
+ def ndc_check ndc
20
+ @ndc_checks << ndc
21
+ self
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,77 @@
1
+ # # Number: A possible phone number, E164 or not.
2
+ # # Hints: Information that helps or constricts the plausibility check.
3
+ # #
4
+ # plausible? number, hints = {}
5
+ #
6
+
7
+ # plausible? number # Uses the definitions from the country definition to plausibility check.
8
+ # plausible? number, cc: 1 # => Checks cc.
9
+ # plausible? number, pattern: /[^5]/ # Uses def, checks against split.
10
+ # plausible? number, country: 1, pattern: [3, 4, 3] # Uses given country – adds cc.
11
+ #
12
+
13
+ # Basic plausibility is:
14
+ # * Max digits are 15.
15
+ # * Min digits are 2 (?)
16
+ #
17
+
18
+ module Phony
19
+
20
+ class Validators
21
+
22
+ def initialize
23
+ @validators = {}
24
+ end
25
+
26
+ def self.instance
27
+ @instance ||= new
28
+ end
29
+
30
+ # Add a specific country validator.
31
+ #
32
+ def add cc, validator
33
+ @validators[cc] = validator
34
+ end
35
+
36
+ # Is the given number plausible?
37
+ #
38
+ def plausible? number, hints = {}
39
+ normalized = CountryCodes.instance.clean number
40
+
41
+ # False if it fails the basic check.
42
+ #
43
+ return false unless (2..15) === normalized.size
44
+
45
+ # Hint based checking.
46
+ #
47
+ cc, ndc, *rest = Phony.split normalized
48
+
49
+ # CC.
50
+ #
51
+ cc_needed = hints[:cc]
52
+ return false if cc_needed && cc_needed != cc
53
+
54
+ # NDC.
55
+ #
56
+ ndc_needed = hints[:ndc]
57
+ return false if ndc_needed && ndc_needed != ndc
58
+
59
+ # Country specific checks.
60
+ #
61
+ validator = validator_for cc
62
+ validator.plausible? ndc, rest
63
+ rescue StandardError
64
+ return false
65
+ end
66
+
67
+ def validator_for cc
68
+ @validators[cc] || default_validator
69
+ end
70
+
71
+ def default_validator
72
+ @default_validator ||= Validator.new
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe 'validations' do
6
+
7
+ describe 'plausible?' do
8
+
9
+ it "is correct" do
10
+ Phony.plausible?('0000000').should be_false
11
+ end
12
+ it "is correct" do
13
+ Phony.plausible?('hello').should be_false
14
+ end
15
+
16
+ it "is correct" do
17
+ Phony.plausible?('+41 44 111 22 33').should be_true
18
+ end
19
+ it "is correct for explicit checks" do
20
+ Phony.plausible?('+41 44 111 22 33', cc: '41').should be_true
21
+ end
22
+ it "is correct for explicit checks" do
23
+ Phony.plausible?('+41 44 111 22 33', ndc: '44').should be_true
24
+ end
25
+ it "is correct for explicit checks" do
26
+ Phony.plausible?('+41 44 111 22 33', cc: '1').should be_false
27
+ end
28
+ it "is correct for explicit checks" do
29
+ Phony.plausible?('+41 44 111 22 33', ndc: '43').should be_false
30
+ end
31
+
32
+ context 'countries' do
33
+
34
+ it "is correct for US numbers" do
35
+ Phony.plausible?('1-800-692-7753').should be_true
36
+ Phony.plausible?('1-911').should be_false
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phony
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.5
4
+ version: 1.6.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-15 00:00:00.000000000 Z
12
+ date: 2012-03-18 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'Fast international phone number (E164 standard) normalizing, splitting
15
15
  and formatting. Lots of formatting options: International (+.., 00..), national
@@ -43,6 +43,8 @@ files:
43
43
  - lib/phony/national_splitters/none.rb
44
44
  - lib/phony/national_splitters/regex.rb
45
45
  - lib/phony/national_splitters/variable.rb
46
+ - lib/phony/validator.rb
47
+ - lib/phony/validators.rb
46
48
  - lib/phony/vanity.rb
47
49
  - lib/phony.rb
48
50
  - README.textile
@@ -57,6 +59,7 @@ files:
57
59
  - spec/lib/phony/national_splitters/none_spec.rb
58
60
  - spec/lib/phony/national_splitters/regex_spec.rb
59
61
  - spec/lib/phony/national_splitters/variable_spec.rb
62
+ - spec/lib/phony/validations_spec.rb
60
63
  - spec/lib/phony/vanity_spec.rb
61
64
  - spec/lib/phony_spec.rb
62
65
  homepage: http://github.com/floere/phony
@@ -96,5 +99,6 @@ test_files:
96
99
  - spec/lib/phony/national_splitters/none_spec.rb
97
100
  - spec/lib/phony/national_splitters/regex_spec.rb
98
101
  - spec/lib/phony/national_splitters/variable_spec.rb
102
+ - spec/lib/phony/validations_spec.rb
99
103
  - spec/lib/phony/vanity_spec.rb
100
104
  - spec/lib/phony_spec.rb