phony 2.20.14 → 2.20.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/phony/config.rb +25 -26
- data/lib/phony/countries/argentina.rb +311 -314
- data/lib/phony/countries/austria.rb +71 -72
- data/lib/phony/countries/bangladesh.rb +27 -28
- data/lib/phony/countries/belarus.rb +110 -111
- data/lib/phony/countries/brazil.rb +92 -92
- data/lib/phony/countries/cambodia.rb +9 -9
- data/lib/phony/countries/china.rb +22 -21
- data/lib/phony/countries/croatia.rb +6 -5
- data/lib/phony/countries/georgia.rb +84 -84
- data/lib/phony/countries/germany.rb +4067 -4068
- data/lib/phony/countries/guinea.rb +8 -8
- data/lib/phony/countries/india.rb +31 -34
- data/lib/phony/countries/indonesia.rb +57 -46
- data/lib/phony/countries/ireland.rb +4 -5
- data/lib/phony/countries/italy.rb +54 -53
- data/lib/phony/countries/japan.rb +456 -456
- data/lib/phony/countries/kyrgyzstan.rb +109 -109
- data/lib/phony/countries/latvia.rb +34 -34
- data/lib/phony/countries/libya.rb +106 -106
- data/lib/phony/countries/malaysia.rb +12 -12
- data/lib/phony/countries/moldova.rb +42 -42
- data/lib/phony/countries/montenegro.rb +24 -20
- data/lib/phony/countries/myanmar.rb +39 -39
- data/lib/phony/countries/namibia.rb +35 -29
- data/lib/phony/countries/nepal.rb +60 -62
- data/lib/phony/countries/netherlands.rb +13 -13
- data/lib/phony/countries/pakistan.rb +134 -110
- data/lib/phony/countries/paraguay.rb +135 -135
- data/lib/phony/countries/russia_kazakhstan_abkhasia_south_ossetia.rb +125 -128
- data/lib/phony/countries/saudi_arabia.rb +5 -5
- data/lib/phony/countries/serbia.rb +47 -39
- data/lib/phony/countries/somalia.rb +18 -18
- data/lib/phony/countries/south_korea.rb +16 -13
- data/lib/phony/countries/sweden.rb +28 -28
- data/lib/phony/countries/taiwan.rb +20 -19
- data/lib/phony/countries/tajikistan.rb +70 -70
- data/lib/phony/countries/turkmenistan.rb +65 -65
- data/lib/phony/countries/ukraine.rb +607 -607
- data/lib/phony/countries/united_kingdom.rb +66 -66
- data/lib/phony/countries/uruguay.rb +40 -41
- data/lib/phony/countries/vietnam.rb +18 -17
- data/lib/phony/countries/zimbabwe.rb +31 -31
- data/lib/phony/countries.rb +440 -443
- data/lib/phony/country.rb +42 -44
- data/lib/phony/country_codes.rb +61 -60
- data/lib/phony/dsl.rb +23 -26
- data/lib/phony/local_splitters/fixed.rb +20 -29
- data/lib/phony/local_splitters/regex.rb +28 -31
- data/lib/phony/national_code.rb +7 -10
- data/lib/phony/national_splitters/default.rb +9 -11
- data/lib/phony/national_splitters/dsl.rb +8 -18
- data/lib/phony/national_splitters/fixed.rb +11 -14
- data/lib/phony/national_splitters/none.rb +7 -11
- data/lib/phony/national_splitters/regex.rb +13 -17
- data/lib/phony/national_splitters/variable.rb +36 -38
- data/lib/phony/trunk_code.rb +16 -18
- data/lib/phony/vanity.rb +12 -13
- data/lib/phony.rb +84 -84
- metadata +5 -39
- data/spec/functional/config_spec.rb +0 -44
- data/spec/functional/plausibility_spec.rb +0 -689
- data/spec/lib/phony/countries_spec.rb +0 -1460
- data/spec/lib/phony/country_codes_spec.rb +0 -227
- data/spec/lib/phony/country_spec.rb +0 -104
- data/spec/lib/phony/dsl_spec.rb +0 -28
- data/spec/lib/phony/local_splitters/fixed_spec.rb +0 -56
- data/spec/lib/phony/local_splitters/regex_spec.rb +0 -94
- data/spec/lib/phony/national_code_spec.rb +0 -61
- data/spec/lib/phony/national_splitters/default_spec.rb +0 -34
- data/spec/lib/phony/national_splitters/fixed_spec.rb +0 -45
- data/spec/lib/phony/national_splitters/none_spec.rb +0 -28
- data/spec/lib/phony/national_splitters/regex_spec.rb +0 -23
- data/spec/lib/phony/national_splitters/variable_spec.rb +0 -35
- data/spec/lib/phony/trunk_code_spec.rb +0 -85
- data/spec/lib/phony/vanity_spec.rb +0 -30
- data/spec/lib/phony_spec.rb +0 -70
data/lib/phony/country.rb
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Phony
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
4
|
class Country
|
8
|
-
|
9
5
|
attr_accessor :codes
|
10
6
|
|
11
7
|
@@international_absolute_format = '+%s%s%s%s%s'
|
12
8
|
@@international_relative_format = '00%s%s%s%s%s'
|
13
9
|
@@national_format = '%s%s%s%s'
|
14
|
-
|
10
|
+
|
15
11
|
@@default_space = ' '
|
16
12
|
@@default_local_space = ' '
|
17
13
|
@@default_parentheses = false
|
18
14
|
|
19
|
-
# TODO Doc.
|
15
|
+
# TODO: Doc.
|
20
16
|
#
|
21
17
|
def initialize *codes
|
22
18
|
@codes = codes
|
@@ -26,8 +22,8 @@ module Phony
|
|
26
22
|
#
|
27
23
|
# Chain two codes together.
|
28
24
|
#
|
29
|
-
def |
|
30
|
-
self.codes =
|
25
|
+
def |(other)
|
26
|
+
self.codes = codes + other.codes
|
31
27
|
self
|
32
28
|
end
|
33
29
|
|
@@ -35,11 +31,11 @@ module Phony
|
|
35
31
|
#
|
36
32
|
# TODO Rewrite.
|
37
33
|
#
|
38
|
-
def with
|
34
|
+
def with(cc, options = {})
|
39
35
|
@cc = cc
|
40
|
-
|
36
|
+
|
41
37
|
@invalid_ndcs = options[:invalid_ndcs]
|
42
|
-
|
38
|
+
|
43
39
|
@format = options[:format]
|
44
40
|
@space = options[:space]
|
45
41
|
@local_space = options[:local_space]
|
@@ -52,43 +48,45 @@ module Phony
|
|
52
48
|
#
|
53
49
|
# @return [Trunk, String (ndc), Array<String> (national pieces)]
|
54
50
|
#
|
55
|
-
def split
|
51
|
+
def split(national_number)
|
56
52
|
_, trunk, ndc, *rest = internal_split national_number
|
57
53
|
[trunk, ndc, *rest]
|
58
54
|
end
|
55
|
+
|
59
56
|
#
|
60
57
|
#
|
61
58
|
# @return [Splitters::Local, Trunk, String (ndc), Array<String> (national pieces)]
|
62
59
|
#
|
63
|
-
def internal_split
|
60
|
+
def internal_split(national_number)
|
64
61
|
trunk = nil
|
65
62
|
@codes.each do |national_splitter|
|
66
63
|
new_trunk, ndc, *rest = national_splitter.split national_number
|
67
64
|
trunk ||= new_trunk
|
68
65
|
return [national_splitter.local_splitter, trunk, ndc, *rest] if rest && !rest.empty?
|
69
66
|
end
|
70
|
-
|
67
|
+
|
71
68
|
# Best effort.
|
72
69
|
[nil, trunk, national_number, []]
|
73
70
|
end
|
74
|
-
|
71
|
+
|
75
72
|
# Format the number, given the national part of it.
|
76
73
|
#
|
77
|
-
def format
|
74
|
+
def format(national_number, options = {})
|
78
75
|
type = options[:format] || @format
|
79
76
|
space = options[:spaces] || @space || @@default_space
|
80
|
-
local_space = options[:local_spaces] || @local_space || space
|
77
|
+
local_space = options[:local_spaces] || @local_space || space || @@default_local_space
|
81
78
|
parentheses = options[:parentheses]
|
82
79
|
parentheses = @parentheses || @@default_parentheses if parentheses.nil?
|
83
80
|
use_trunk = options[:trunk]
|
84
|
-
|
81
|
+
|
85
82
|
trunk, ndc, *local_pieces = split national_number
|
86
|
-
|
83
|
+
|
87
84
|
local = format_local local_pieces, local_space
|
88
|
-
|
85
|
+
|
89
86
|
format_cc_ndc trunk, ndc, local, type, space, parentheses, use_trunk
|
90
87
|
end
|
91
|
-
|
88
|
+
|
89
|
+
def format_local(local, local_space)
|
92
90
|
if local.empty?
|
93
91
|
EMPTY_STRING
|
94
92
|
else
|
@@ -96,14 +94,15 @@ module Phony
|
|
96
94
|
local.join local_space.to_s
|
97
95
|
end
|
98
96
|
end
|
99
|
-
|
100
|
-
|
97
|
+
|
98
|
+
def format_cc_ndc(trunk, ndc, local, type, space, parentheses, use_trunk)
|
99
|
+
# NOTE: We mark NDCs that are of type "none" with false (nil trips plausible?). This would result in false being printed.
|
101
100
|
# Therefore we set NDC to nil when formatting.
|
102
101
|
ndc = nil if ndc == false
|
103
102
|
case type
|
104
103
|
when String
|
105
104
|
trunk &&= trunk.format(space, use_trunk)
|
106
|
-
type % { :
|
105
|
+
type % { trunk: trunk, cc: @cc, ndc: ndc, local: local }
|
107
106
|
when nil, :international_absolute, :international, :+
|
108
107
|
if ndc
|
109
108
|
format_with_ndc(@@international_absolute_format, @cc, format_ndc(ndc, parentheses), local, space)
|
@@ -121,20 +120,23 @@ module Phony
|
|
121
120
|
if ndc && !ndc.empty?
|
122
121
|
@@national_format % [trunk, format_ndc(ndc, parentheses), space, local]
|
123
122
|
else
|
124
|
-
@@national_format % [trunk, nil, nil,
|
123
|
+
@@national_format % [trunk, nil, nil, local]
|
125
124
|
end
|
126
125
|
when :local
|
127
126
|
local
|
128
127
|
end
|
129
128
|
end
|
130
|
-
|
129
|
+
|
130
|
+
def format_ndc(ndc, parentheses)
|
131
131
|
ndc = nil if ndc == false # TODO
|
132
132
|
parentheses ? "(#{ndc})" : ndc
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
|
+
def format_with_ndc(format, cc, ndc, local, space)
|
135
136
|
format % [cc, space, ndc, space, local]
|
136
137
|
end
|
137
|
-
|
138
|
+
|
139
|
+
def format_without_ndc(format, cc, local, space)
|
138
140
|
format % [cc, space, local, nil, nil]
|
139
141
|
end
|
140
142
|
|
@@ -143,12 +145,13 @@ module Phony
|
|
143
145
|
@@basic_cleaning_pattern = /\(0|\D/
|
144
146
|
# Clean number of all non-numeric characters and return a copy.
|
145
147
|
#
|
146
|
-
def clean
|
148
|
+
def clean(number)
|
147
149
|
clean! number && number.dup
|
148
150
|
end
|
151
|
+
|
149
152
|
# Clean number of all non-numeric characters and return it.
|
150
153
|
#
|
151
|
-
def clean!
|
154
|
+
def clean!(number)
|
152
155
|
number.gsub!(@@basic_cleaning_pattern, EMPTY_STRING) || number
|
153
156
|
end
|
154
157
|
|
@@ -162,21 +165,19 @@ module Phony
|
|
162
165
|
#
|
163
166
|
# Note: Options such as CC
|
164
167
|
#
|
165
|
-
def normalize
|
168
|
+
def normalize(national_number, options = {})
|
166
169
|
clean! national_number
|
167
|
-
|
170
|
+
@codes.each_with_object national_number do |code, number|
|
168
171
|
result = code.normalize number, options
|
169
172
|
break result if result
|
170
|
-
number
|
171
173
|
end
|
172
|
-
normalized
|
173
174
|
end
|
174
175
|
|
175
176
|
# Tests for plausibility of this national number.
|
176
177
|
#
|
177
|
-
def plausible?
|
178
|
+
def plausible?(rest, hints = {})
|
178
179
|
local, _, ndc, *rest = internal_split rest
|
179
|
-
|
180
|
+
|
180
181
|
# Element based checking.
|
181
182
|
#
|
182
183
|
# Note: ndc == false means the country has none.
|
@@ -193,28 +194,25 @@ module Phony
|
|
193
194
|
#
|
194
195
|
ndc_needed = hints[:ndc]
|
195
196
|
return false if ndc_needed && !(ndc_needed === ndc)
|
196
|
-
|
197
|
+
|
197
198
|
# If there is no local part, we can assume it's not a plausible number.
|
198
199
|
# (Or, not defined correctly in Phony yet)
|
199
200
|
return false unless local
|
200
201
|
|
201
202
|
# Local code specific checks.
|
202
203
|
#
|
203
|
-
|
204
|
+
local.plausible? rest, hints
|
204
205
|
end
|
205
206
|
|
206
207
|
# Is this national number a vanity number?
|
207
208
|
#
|
208
|
-
def vanity?
|
209
|
+
def vanity?(national_number)
|
209
210
|
Vanity.vanity? national_number
|
210
211
|
end
|
211
|
-
|
212
|
-
|
213
|
-
def vanity_to_number vanity_number
|
212
|
+
|
213
|
+
def vanity_to_number(vanity_number)
|
214
214
|
_, ndc, *rest = split vanity_number
|
215
215
|
"#{ndc}#{Vanity.replace(rest.join)}"
|
216
216
|
end
|
217
|
-
|
218
217
|
end
|
219
|
-
|
220
218
|
end
|
data/lib/phony/country_codes.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Phony
|
3
4
|
EMPTY_STRING = '' unless defined?(EMPTY_STRING)
|
4
5
|
|
5
6
|
# Handles determining the correct national code handler.
|
6
7
|
#
|
7
8
|
class CountryCodes
|
8
|
-
|
9
9
|
attr_reader :countries
|
10
10
|
attr_accessor :international_absolute_format, :international_relative_format, :national_format
|
11
11
|
|
@@ -14,11 +14,11 @@ module Phony
|
|
14
14
|
def self.instance
|
15
15
|
@instance ||= new
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
# Add the given country to the mapping under the
|
19
19
|
# given country code.
|
20
20
|
#
|
21
|
-
def add
|
21
|
+
def add(country_code, country)
|
22
22
|
country_code = country_code.to_s
|
23
23
|
optimized_country_code_access = country_code.size
|
24
24
|
|
@@ -29,7 +29,7 @@ module Phony
|
|
29
29
|
|
30
30
|
# Get the Country object for the given CC.
|
31
31
|
#
|
32
|
-
def []
|
32
|
+
def [](cc)
|
33
33
|
countries[cc.size][cc]
|
34
34
|
end
|
35
35
|
|
@@ -38,12 +38,13 @@ module Phony
|
|
38
38
|
@@basic_cleaning_pattern = /\A00?|\(0|\D/
|
39
39
|
# Clean number of all non-numeric characters, initial zeros or (0 and return it.
|
40
40
|
#
|
41
|
-
def clean
|
41
|
+
def clean(number)
|
42
42
|
clean! number && number.dup
|
43
43
|
end
|
44
|
+
|
44
45
|
# Clean number of all non-numeric characters, initial zeros or (0 and return a copy.
|
45
46
|
#
|
46
|
-
def clean!
|
47
|
+
def clean!(number)
|
47
48
|
number.gsub!(@@basic_cleaning_pattern, EMPTY_STRING) || number
|
48
49
|
end
|
49
50
|
|
@@ -58,33 +59,33 @@ module Phony
|
|
58
59
|
# * (0) anywhere.
|
59
60
|
# * Non-digits.
|
60
61
|
#
|
61
|
-
def normalize
|
62
|
-
country = if cc = options[:cc]
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
62
|
+
def normalize(number, options = {})
|
63
|
+
country = if (cc = options[:cc])
|
64
|
+
self[cc]
|
65
|
+
else
|
66
|
+
clean! number
|
67
|
+
country, cc, number = partial_split number
|
68
|
+
country
|
69
|
+
end
|
69
70
|
number = country.normalize number, cc: cc
|
70
71
|
countrify! number, cc
|
71
72
|
end
|
72
73
|
|
73
74
|
# Splits this number into cc, ndc and locally split number parts.
|
74
75
|
#
|
75
|
-
def split
|
76
|
+
def split(number)
|
76
77
|
# Split the number into country, cc, and national part.
|
77
78
|
country, cc, national_number = partial_split number
|
78
|
-
|
79
|
+
|
79
80
|
# Split the national number into ndc and local part.
|
80
81
|
_, ndc, *local = country.split national_number
|
81
|
-
|
82
|
+
|
82
83
|
[cc, ndc, *local]
|
83
84
|
end
|
84
85
|
|
85
86
|
# Format the number.
|
86
87
|
#
|
87
|
-
def format
|
88
|
+
def format(number, options = {})
|
88
89
|
country, _, national_number = partial_split number
|
89
90
|
country.format national_number, options
|
90
91
|
end
|
@@ -92,22 +93,22 @@ module Phony
|
|
92
93
|
|
93
94
|
# Is this number plausible?
|
94
95
|
#
|
95
|
-
def plausible?
|
96
|
+
def plausible?(number, hints = {})
|
96
97
|
normalized = clean number
|
97
98
|
|
98
99
|
# False if it fails the basic check.
|
99
100
|
#
|
100
|
-
return false unless (4..16)
|
101
|
+
return false unless (4..16).include?(normalized.size) # unless hints[:check_length] == false
|
101
102
|
|
102
103
|
country, cc, rest = partial_split normalized
|
103
|
-
|
104
|
+
|
104
105
|
# Was a country calling code given?
|
105
106
|
#
|
106
|
-
if ccc = hints[:ccc]
|
107
|
+
if (ccc = hints[:ccc])
|
107
108
|
cc, ndc, *local = split ccc
|
108
|
-
|
109
|
+
|
109
110
|
raise ArgumentError.new("The provided ccc option is too long and includes more than a cc ('#{cc}') and ndc ('#{ndc}'). It also includes '#{local.join}'.") unless local.size == 1 && local[0].empty?
|
110
|
-
|
111
|
+
|
111
112
|
hints[:cc] = cc
|
112
113
|
hints[:ndc] = ndc
|
113
114
|
end
|
@@ -123,55 +124,55 @@ module Phony
|
|
123
124
|
rescue ArgumentError
|
124
125
|
raise
|
125
126
|
rescue StandardError
|
126
|
-
|
127
|
+
false
|
127
128
|
end
|
128
|
-
|
129
|
+
|
129
130
|
# Is the given number a vanity number?
|
130
131
|
#
|
131
|
-
def vanity?
|
132
|
+
def vanity?(number)
|
132
133
|
country, _, national = partial_split number
|
133
134
|
country.vanity? national
|
134
135
|
end
|
136
|
+
|
135
137
|
# Converts a vanity number into a normalized E164 number.
|
136
138
|
#
|
137
|
-
def vanity_to_number
|
139
|
+
def vanity_to_number(vanity_number)
|
138
140
|
country, cc, national = partial_split vanity_number
|
139
141
|
"#{cc}#{country.vanity_to_number(national)}"
|
140
142
|
end
|
141
143
|
|
142
144
|
private
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
end
|
160
|
-
# This line is never reached as CCs are in prefix code.
|
161
|
-
end
|
162
|
-
|
163
|
-
# Adds the country code to the front
|
164
|
-
# if it does not already start with it.
|
165
|
-
#
|
166
|
-
# Note: This won't be correct in some cases, but it is the best we can do.
|
167
|
-
#
|
168
|
-
def countrify number, cc
|
169
|
-
countrify!(number, cc) || number
|
170
|
-
end
|
171
|
-
def countrify! number, cc
|
172
|
-
number.sub!(/\A/, cc) # @countrify_regex, @cc
|
145
|
+
|
146
|
+
# Return a country for the number.
|
147
|
+
#
|
148
|
+
def country_for(number)
|
149
|
+
country, = partial_split number
|
150
|
+
country
|
151
|
+
end
|
152
|
+
|
153
|
+
# Split off the country and the cc, and also return the national number part.
|
154
|
+
#
|
155
|
+
def partial_split(number)
|
156
|
+
cc = +''
|
157
|
+
1.upto(3) do |i|
|
158
|
+
cc << number.slice!(0..0)
|
159
|
+
country = countries[i][cc]
|
160
|
+
return [country, cc, number] if country
|
173
161
|
end
|
162
|
+
# This line is never reached as CCs are in prefix code.
|
163
|
+
end
|
174
164
|
|
175
|
-
|
165
|
+
# Adds the country code to the front
|
166
|
+
# if it does not already start with it.
|
167
|
+
#
|
168
|
+
# Note: This won't be correct in some cases, but it is the best we can do.
|
169
|
+
#
|
170
|
+
def countrify(number, cc)
|
171
|
+
countrify!(number, cc) || number
|
172
|
+
end
|
176
173
|
|
174
|
+
def countrify!(number, cc)
|
175
|
+
number.sub!(/\A/, cc) # @countrify_regex, @cc
|
176
|
+
end
|
177
|
+
end
|
177
178
|
end
|
data/lib/phony/dsl.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Phony
|
3
4
|
# For country definitions.
|
4
5
|
#
|
5
6
|
# There are two styles: With or without block.
|
@@ -27,7 +28,6 @@ module Phony
|
|
27
28
|
# Phony.define { ... }
|
28
29
|
#
|
29
30
|
class DSL
|
30
|
-
|
31
31
|
# Define a country's rules.
|
32
32
|
#
|
33
33
|
# Use the other DSL methods to define the country's rules.
|
@@ -40,13 +40,13 @@ module Phony
|
|
40
40
|
# @example Add a country with country code 27.
|
41
41
|
# country '27', # CC, followed by rules, for example fixed(2) >> ...
|
42
42
|
#
|
43
|
-
def country
|
43
|
+
def country(country_code, definition, options = {})
|
44
44
|
return unless Phony.config.load?(country_code)
|
45
|
-
|
45
|
+
|
46
46
|
definition.with country_code, options
|
47
47
|
Phony::CountryCodes.instance.add country_code, definition
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# Designates a country code as reserved.
|
51
51
|
# A reserved country will result in an exception when trying to be used.
|
52
52
|
#
|
@@ -57,10 +57,10 @@ module Phony
|
|
57
57
|
# @example Designate country code 27 as reserved.
|
58
58
|
# reserved('27')
|
59
59
|
#
|
60
|
-
def reserved
|
60
|
+
def reserved(country_code)
|
61
61
|
# Does nothing, will just fail with an exception.
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# Define a country to use default rules (and to be done at some point).
|
65
65
|
#
|
66
66
|
# @return Rules for a country.
|
@@ -71,7 +71,7 @@ module Phony
|
|
71
71
|
def todo
|
72
72
|
none >> split(10)
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
# This country uses a trunk code.
|
76
76
|
#
|
77
77
|
# @param [String] code The trunk code.
|
@@ -88,7 +88,7 @@ module Phony
|
|
88
88
|
# @example Most countries which use a trunk code use 0. E.g. Romania.
|
89
89
|
# country '40', trunk('0') | ...
|
90
90
|
#
|
91
|
-
def trunk
|
91
|
+
def trunk(code, options = {})
|
92
92
|
TrunkCode.new code, options
|
93
93
|
end
|
94
94
|
|
@@ -107,11 +107,11 @@ module Phony
|
|
107
107
|
# @example France. Uses a fixed NDC of size 1.
|
108
108
|
# country '33', fixed(1) >> split(2,2,2,2)
|
109
109
|
#
|
110
|
-
def fixed
|
110
|
+
def fixed(length, options = {})
|
111
111
|
options[:zero] = true if options[:zero].nil?
|
112
112
|
NationalSplitters::Fixed.instance_for length, options
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
# Marks the country as not using an NDC. This rule will always match.
|
116
116
|
#
|
117
117
|
# @return NationalSplitters::None A no-ndc national splitter.
|
@@ -121,7 +121,7 @@ module Phony
|
|
121
121
|
def none
|
122
122
|
NationalSplitters::None.instance_for
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
# If you have a number of (possibly) variable length NDCs
|
126
126
|
# that cannot be well expressed via regexp, use this.
|
127
127
|
#
|
@@ -135,15 +135,15 @@ module Phony
|
|
135
135
|
# one_of('103', '105') >> split(3,3)
|
136
136
|
#
|
137
137
|
def one_of *ndcs
|
138
|
-
options =
|
138
|
+
options = ndcs.last.is_a?(Hash) ? ndcs.pop : {}
|
139
139
|
|
140
140
|
# Ruby 1.8 compatibility mode.
|
141
141
|
#
|
142
|
-
ndcs = ndcs.first if
|
142
|
+
ndcs = ndcs.first if ndcs.first.is_a?(Array)
|
143
143
|
|
144
144
|
NationalSplitters::Variable.new options[:max_length], ndcs.map(&:freeze)
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
# If you have a number of (possibly) variable length NDCs
|
148
148
|
# that can be well expressed via regexp, use this.
|
149
149
|
#
|
@@ -157,11 +157,11 @@ module Phony
|
|
157
157
|
# match(/^(33|55|81)\d+$/) >> split(2,2,2,2) |
|
158
158
|
# match(/^(\d{3})\d+$/) >> split(3,2,2)
|
159
159
|
#
|
160
|
-
def match
|
160
|
+
def match(regex, options = {})
|
161
161
|
# Check if regexp has a group in it.
|
162
162
|
#
|
163
|
-
raise "Regexp /#{regex.source}/ needs a group in it that defines which digits belong to the NDC." unless regex.source
|
164
|
-
|
163
|
+
raise "Regexp /#{regex.source}/ needs a group in it that defines which digits belong to the NDC." unless /\(/.match?(regex.source)
|
164
|
+
|
165
165
|
NationalSplitters::Regex.instance_for regex, options[:on_fail_take], options
|
166
166
|
end
|
167
167
|
|
@@ -183,7 +183,7 @@ module Phony
|
|
183
183
|
# local << local.pop + 10 # Allow for call-through numbers with an arbitrary size.
|
184
184
|
LocalSplitters::Fixed.instance_for local
|
185
185
|
end
|
186
|
-
|
186
|
+
|
187
187
|
# Matches on the rest of the number and splits according
|
188
188
|
# to the given value for the regexp key.
|
189
189
|
#
|
@@ -199,18 +199,18 @@ module Phony
|
|
199
199
|
# /^[489].*$/ => [3,2,3],
|
200
200
|
# :fallback => [2,2,2,2])
|
201
201
|
#
|
202
|
-
def matched_split
|
202
|
+
def matched_split(options = {})
|
203
203
|
LocalSplitters::Regex.instance_for options
|
204
204
|
end
|
205
|
-
|
205
|
+
|
206
206
|
# Validators
|
207
207
|
#
|
208
|
-
|
208
|
+
|
209
209
|
# Which NDCs are explicitly invalid?
|
210
210
|
#
|
211
211
|
# @param [Regexp, String] ndc A regexp or a string of invalid NDCs.
|
212
212
|
#
|
213
|
-
# @return Validators::NDC An NDC validator
|
213
|
+
# @return Validators::NDC An NDC validator
|
214
214
|
#
|
215
215
|
# @example NANP
|
216
216
|
# country '1',
|
@@ -220,8 +220,5 @@ module Phony
|
|
220
220
|
def invalid_ndcs *ndc
|
221
221
|
Validators::NDC.new invalid: ndc
|
222
222
|
end
|
223
|
-
|
224
|
-
|
225
223
|
end
|
226
|
-
|
227
224
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Phony
|
2
|
-
|
3
4
|
module LocalSplitters
|
4
|
-
|
5
5
|
# Local splitter class to split the last part of
|
6
6
|
# a number, i.e. minus cc or ndc.
|
7
7
|
#
|
@@ -11,64 +11,55 @@ module Phony
|
|
11
11
|
# to avoid getting new local splitter instances.
|
12
12
|
#
|
13
13
|
class Fixed
|
14
|
-
|
15
14
|
@mapping = {}
|
16
|
-
|
15
|
+
|
17
16
|
# Get a splitter for the given format.
|
18
17
|
#
|
19
18
|
# Caches the created splitter for the given format.
|
20
19
|
#
|
21
|
-
def self.instance_for
|
20
|
+
def self.instance_for(format = nil)
|
22
21
|
@mapping[format] ||= new(format)
|
23
22
|
end
|
24
|
-
|
23
|
+
|
25
24
|
# Initialize with a local format, like [3, 2, 2] (also the default).
|
26
25
|
#
|
27
26
|
# The format [3, 2, 2] splits a number like '3332222' into ['333', '22', '22'].
|
28
27
|
#
|
29
|
-
def initialize
|
30
|
-
format = format
|
28
|
+
def initialize(format = nil)
|
29
|
+
format = format&.dup || [3, 2, 2]
|
31
30
|
@format, @length = extract_params format
|
32
31
|
@format << @format.pop + 10
|
33
32
|
end
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
def extract_params format
|
33
|
+
|
34
|
+
def extract_params(format)
|
38
35
|
if format.last.respond_to? :max
|
39
36
|
last = format.pop
|
40
|
-
length = format.
|
41
|
-
length = (length+last.min..length+last.max)
|
37
|
+
length = format.sum
|
38
|
+
length = (length + last.min..length + last.max)
|
42
39
|
format << last.min
|
43
40
|
else
|
44
|
-
length = format.
|
41
|
+
length = format.sum
|
45
42
|
end
|
46
43
|
[format, length]
|
47
44
|
end
|
48
|
-
|
45
|
+
|
49
46
|
# Split a local number according to an assumed country specific format.
|
50
47
|
#
|
51
48
|
# Examples
|
52
49
|
# * split '3643533' # => ['364', '35', '33'] # (Switzerland)
|
53
50
|
#
|
54
|
-
def split
|
55
|
-
@format.
|
56
|
-
result << number.slice!(0..size-1)
|
51
|
+
def split(number)
|
52
|
+
@format.each_with_object([]) do |size, result|
|
53
|
+
result << number.slice!(0..size - 1)
|
57
54
|
return result if number.empty?
|
58
|
-
result
|
59
55
|
end
|
60
56
|
end
|
61
|
-
|
62
|
-
|
63
|
-
#
|
64
|
-
def plausible? rest, hints = {}
|
57
|
+
|
58
|
+
def plausible?(rest, hints = {})
|
65
59
|
return true if hints[:check_length] == false
|
66
|
-
|
60
|
+
|
67
61
|
@length === rest.inject(0) { |total, part| total + part.size }
|
68
62
|
end
|
69
|
-
|
70
63
|
end
|
71
|
-
|
72
64
|
end
|
73
|
-
|
74
|
-
end
|
65
|
+
end
|