phony 1.9.0 → 2.19.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.textile +64 -112
- data/lib/phony/config.rb +91 -0
- data/lib/phony/countries/argentina.rb +355 -0
- data/lib/phony/countries/austria.rb +56 -22
- data/lib/phony/countries/bangladesh.rb +57 -0
- data/lib/phony/countries/belarus.rb +133 -0
- data/lib/phony/countries/brazil.rb +101 -95
- data/lib/phony/countries/cambodia.rb +131 -0
- data/lib/phony/countries/china.rb +13 -6
- data/lib/phony/countries/croatia.rb +23 -0
- data/lib/phony/countries/georgia.rb +94 -0
- data/lib/phony/countries/germany.rb +66 -42
- data/lib/phony/countries/guinea.rb +46 -0
- data/lib/phony/countries/india.rb +50 -0
- data/lib/phony/countries/indonesia.rb +55 -0
- data/lib/phony/countries/ireland.rb +35 -28
- data/lib/phony/countries/italy.rb +272 -166
- data/lib/phony/countries/japan.rb +468 -0
- data/lib/phony/countries/kyrgyzstan.rb +120 -0
- data/lib/phony/countries/latvia.rb +43 -0
- data/lib/phony/countries/libya.rb +116 -0
- data/lib/phony/countries/malaysia.rb +31 -7
- data/lib/phony/countries/moldova.rb +53 -0
- data/lib/phony/countries/montenegro.rb +30 -0
- data/lib/phony/countries/myanmar.rb +55 -0
- data/lib/phony/countries/namibia.rb +37 -0
- data/lib/phony/countries/nepal.rb +73 -0
- data/lib/phony/countries/netherlands.rb +17 -5
- data/lib/phony/countries/pakistan.rb +121 -0
- data/lib/phony/countries/paraguay.rb +147 -0
- data/lib/phony/countries/{russia_kazakhstan_abhasia_south_osetia.rb → russia_kazakhstan_abkhasia_south_ossetia.rb} +35 -24
- data/lib/phony/countries/saudi_arabia.rb +40 -0
- data/lib/phony/countries/serbia.rb +47 -0
- data/lib/phony/countries/somalia.rb +26 -0
- data/lib/phony/countries/south_korea.rb +19 -10
- data/lib/phony/countries/sweden.rb +58 -38
- data/lib/phony/countries/taiwan.rb +28 -0
- data/lib/phony/countries/tajikistan.rb +79 -0
- data/lib/phony/countries/turkmenistan.rb +76 -0
- data/lib/phony/countries/ukraine.rb +630 -0
- data/lib/phony/countries/united_kingdom.rb +639 -44
- data/lib/phony/countries/uruguay.rb +53 -0
- data/lib/phony/countries/vietnam.rb +133 -0
- data/lib/phony/countries/zimbabwe.rb +39 -0
- data/lib/phony/countries.rb +901 -301
- data/lib/phony/country.rb +177 -20
- data/lib/phony/country_codes.rb +119 -101
- data/lib/phony/dsl.rb +113 -68
- data/lib/phony/local_splitters/fixed.rb +25 -1
- data/lib/phony/local_splitters/regex.rb +16 -2
- data/lib/phony/national_code.rb +7 -7
- data/lib/phony/national_splitters/default.rb +35 -3
- data/lib/phony/national_splitters/dsl.rb +12 -7
- data/lib/phony/national_splitters/fixed.rb +7 -1
- data/lib/phony/national_splitters/none.rb +7 -3
- data/lib/phony/national_splitters/regex.rb +6 -0
- data/lib/phony/national_splitters/variable.rb +13 -9
- data/lib/phony/trunk_code.rb +57 -0
- data/lib/phony/vanity.rb +3 -3
- data/lib/phony.rb +239 -55
- data/spec/functional/config_spec.rb +44 -0
- data/spec/functional/plausibility_spec.rb +656 -0
- data/spec/lib/phony/countries_spec.rb +1207 -119
- data/spec/lib/phony/country_codes_spec.rb +99 -81
- data/spec/lib/phony/country_spec.rb +54 -14
- data/spec/lib/phony/dsl_spec.rb +2 -2
- data/spec/lib/phony/local_splitters/fixed_spec.rb +4 -4
- data/spec/lib/phony/local_splitters/regex_spec.rb +50 -2
- data/spec/lib/phony/national_code_spec.rb +34 -34
- data/spec/lib/phony/national_splitters/default_spec.rb +34 -0
- data/spec/lib/phony/national_splitters/fixed_spec.rb +12 -6
- data/spec/lib/phony/national_splitters/none_spec.rb +13 -3
- data/spec/lib/phony/national_splitters/regex_spec.rb +1 -1
- data/spec/lib/phony/national_splitters/variable_spec.rb +11 -5
- data/spec/lib/phony/trunk_code_spec.rb +85 -0
- data/spec/lib/phony/vanity_spec.rb +15 -19
- data/spec/lib/phony_spec.rb +59 -277
- metadata +67 -34
- data/lib/phony/validator.rb +0 -26
- data/lib/phony/validators.rb +0 -88
- data/spec/lib/phony/validations_spec.rb +0 -109
data/lib/phony/dsl.rb
CHANGED
@@ -1,27 +1,3 @@
|
|
1
|
-
# # Switzerland (simplified):
|
2
|
-
# #
|
3
|
-
# country('41', fixed(2) >> local([3,2,2]))
|
4
|
-
#
|
5
|
-
# # Germany. Too big, we use a separate file:
|
6
|
-
# #
|
7
|
-
# Phony.define do
|
8
|
-
# country '49', match(...) >> split([...]) ||
|
9
|
-
# one_of([...], :max_length => 5) >> split([...])
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# # Denmark:
|
13
|
-
# #
|
14
|
-
# country('45', none >> split([2,2,2,2]))
|
15
|
-
#
|
16
|
-
# # Hungary:
|
17
|
-
# #
|
18
|
-
# country('36',
|
19
|
-
# match(/^104|105|107|112/) >> split([3,3]) ||
|
20
|
-
# one_of([1], :max_length => 2) >> split([3,4])
|
21
|
-
# )
|
22
|
-
#
|
23
|
-
# Note: Perhaps the DSL should operate directly on country codes.
|
24
|
-
#
|
25
1
|
module Phony
|
26
2
|
|
27
3
|
# For country definitions.
|
@@ -36,22 +12,84 @@ module Phony
|
|
36
12
|
#
|
37
13
|
# Phony.define.country ...
|
38
14
|
#
|
39
|
-
def self.define
|
15
|
+
def self.define(&block)
|
40
16
|
dsl = DSL.new
|
41
|
-
dsl.instance_eval
|
17
|
+
dsl.instance_eval(&block) if block_given?
|
42
18
|
dsl
|
43
19
|
end
|
44
20
|
|
21
|
+
# Contains a number of DSL methods. Is used e.g. in the countries.rb file.
|
22
|
+
#
|
23
|
+
# Do not use directly, but instead use {Phony.define} to execute a block
|
24
|
+
# in the DSL instance's context.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# Phony.define { ... }
|
28
|
+
#
|
45
29
|
class DSL
|
46
30
|
|
47
|
-
#
|
31
|
+
# Define a country's rules.
|
32
|
+
#
|
33
|
+
# Use the other DSL methods to define the country's rules.
|
34
|
+
#
|
35
|
+
# @param [String] country_code The country code of the country.
|
36
|
+
# @param [Phony::CountryCodes] definition Rules for this country.
|
37
|
+
#
|
38
|
+
# @return Undefined.
|
48
39
|
#
|
49
|
-
#
|
40
|
+
# @example Add a country with country code 27.
|
50
41
|
# country '27', # CC, followed by rules, for example fixed(2) >> ...
|
51
42
|
#
|
52
|
-
def country country_code,
|
53
|
-
Phony
|
54
|
-
|
43
|
+
def country country_code, definition, options = {}
|
44
|
+
return unless Phony.config.load?(country_code)
|
45
|
+
|
46
|
+
definition.with country_code, options
|
47
|
+
Phony::CountryCodes.instance.add country_code, definition
|
48
|
+
end
|
49
|
+
|
50
|
+
# Designates a country code as reserved.
|
51
|
+
# A reserved country will result in an exception when trying to be used.
|
52
|
+
#
|
53
|
+
# @param [String] country_code The country code of the country.
|
54
|
+
#
|
55
|
+
# @return nil
|
56
|
+
#
|
57
|
+
# @example Designate country code 27 as reserved.
|
58
|
+
# reserved('27')
|
59
|
+
#
|
60
|
+
def reserved country_code
|
61
|
+
# Does nothing, will just fail with an exception.
|
62
|
+
end
|
63
|
+
|
64
|
+
# Define a country to use default rules (and to be done at some point).
|
65
|
+
#
|
66
|
+
# @return Rules for a country.
|
67
|
+
#
|
68
|
+
# @example Define country 27 to use default rules.
|
69
|
+
# country '27', todo
|
70
|
+
#
|
71
|
+
def todo
|
72
|
+
none >> split(10)
|
73
|
+
end
|
74
|
+
|
75
|
+
# This country uses a trunk code.
|
76
|
+
#
|
77
|
+
# @param [String] code The trunk code.
|
78
|
+
# @param [Hash] options Options hash. Pass :normalize (true/false) to indicate whether it needs to be normalized.
|
79
|
+
#
|
80
|
+
# @return TrunkCode A trunk code handler.
|
81
|
+
#
|
82
|
+
# @example Hungary uses 06.
|
83
|
+
# country '36', trunk('06', normalize: false) | ...
|
84
|
+
#
|
85
|
+
# @example North America uses 1.
|
86
|
+
# country '1', trunk('1%s', normalize: true) | ...
|
87
|
+
#
|
88
|
+
# @example Most countries which use a trunk code use 0. E.g. Romania.
|
89
|
+
# country '40', trunk('0') | ...
|
90
|
+
#
|
91
|
+
def trunk code, options = {}
|
92
|
+
TrunkCode.new code, options
|
55
93
|
end
|
56
94
|
|
57
95
|
# National matcher & splitters.
|
@@ -61,25 +99,24 @@ module Phony
|
|
61
99
|
# uses a zero prefix when formatted
|
62
100
|
# with format :national.
|
63
101
|
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
# * options: Set :zero to false to not add a zero on format :national.
|
102
|
+
# @param [Fixnum] length The length of the fixed length NDC.
|
103
|
+
# @param [Hash] options An options hash (set zero: false to not add a zero on format :national).
|
67
104
|
#
|
68
|
-
#
|
69
|
-
#
|
105
|
+
# @return NationalSplitters::Fixed A fixed length national splitter.
|
106
|
+
#
|
107
|
+
# @example France. Uses a fixed NDC of size 1.
|
108
|
+
# country '33', fixed(1) >> split(2,2,2,2)
|
70
109
|
#
|
71
110
|
def fixed length, options = {}
|
72
111
|
options[:zero] = true if options[:zero].nil?
|
73
112
|
NationalSplitters::Fixed.instance_for length, options
|
74
113
|
end
|
75
114
|
|
76
|
-
#
|
115
|
+
# Marks the country as not using an NDC. This rule will always match.
|
116
|
+
#
|
117
|
+
# @return NationalSplitters::None A no-ndc national splitter.
|
77
118
|
#
|
78
|
-
#
|
79
|
-
# * Denmark
|
80
|
-
# * Norway
|
81
|
-
# * Iceland
|
82
|
-
# (and more)
|
119
|
+
# @example Denmark, Norway, Iceland.
|
83
120
|
#
|
84
121
|
def none
|
85
122
|
NationalSplitters::None.instance_for
|
@@ -88,12 +125,14 @@ module Phony
|
|
88
125
|
# If you have a number of (possibly) variable length NDCs
|
89
126
|
# that cannot be well expressed via regexp, use this.
|
90
127
|
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
128
|
+
# @param [Array<String>] ndcs A list of NDCs of variable length. Can contain :max_length => number to denote a maximum NDC length.
|
129
|
+
#
|
130
|
+
# @return NationalSplitters::Variable A variable size national splitter.
|
94
131
|
#
|
95
|
-
#
|
96
|
-
# country '51',
|
132
|
+
# @example With two NDCs
|
133
|
+
# country '51',
|
134
|
+
# # If it's either 103 or 105, then split ...
|
135
|
+
# one_of('103', '105') >> split(3,3)
|
97
136
|
#
|
98
137
|
def one_of *ndcs
|
99
138
|
options = Hash === ndcs.last ? ndcs.pop : {}
|
@@ -102,16 +141,17 @@ module Phony
|
|
102
141
|
#
|
103
142
|
ndcs = ndcs.first if Array === ndcs.first
|
104
143
|
|
105
|
-
NationalSplitters::Variable.new options[:max_length], ndcs
|
144
|
+
NationalSplitters::Variable.new options[:max_length], ndcs.map(&:freeze)
|
106
145
|
end
|
107
146
|
|
108
147
|
# If you have a number of (possibly) variable length NDCs
|
109
148
|
# that can be well expressed via regexp, use this.
|
110
149
|
#
|
111
|
-
#
|
112
|
-
# * regex A regexp describing the NDCs (First group must contain the NDC, eg. /^(0\d{2})\d+$/) contains all NDCs with 0xx...
|
150
|
+
# @param [Regexp] regex A Regexp describing the NDCs (First group must contain the NDC, eg. /^(0\d{2})\d+$/) contains all NDCs with 0xx...
|
113
151
|
#
|
114
|
-
#
|
152
|
+
# @return NationalSplitters::Regex A regexp-based national splitter.
|
153
|
+
#
|
154
|
+
# @example With several NDC matchers.
|
115
155
|
# country '52',
|
116
156
|
# match(/^(0\d{2})\d+$/) >> split(2,2,2,2) |
|
117
157
|
# match(/^(33|55|81)\d+$/) >> split(2,2,2,2) |
|
@@ -122,43 +162,45 @@ module Phony
|
|
122
162
|
#
|
123
163
|
raise "Regexp /#{regex.source}/ needs a group in it that defines which digits belong to the NDC." unless regex.source =~ /\(/
|
124
164
|
|
125
|
-
on_fail_take = options.delete :on_fail_take
|
126
165
|
NationalSplitters::Regex.instance_for regex, options[:on_fail_take], options
|
127
166
|
end
|
128
|
-
|
129
|
-
# This country still uses a default NDC (and needs to be done, hence the todo).
|
130
|
-
#
|
131
|
-
def todo
|
132
|
-
none >> NationalSplitters::Default.instance_for
|
133
|
-
end
|
134
167
|
|
135
168
|
# Local splitters.
|
136
169
|
#
|
137
170
|
|
138
171
|
# Splits the number into groups of given sizes.
|
139
172
|
#
|
140
|
-
#
|
173
|
+
# Also takes ranges.
|
174
|
+
#
|
175
|
+
# @param [Array<Fixnum>] local The local group sizes to split the local number part into.
|
176
|
+
#
|
177
|
+
# @return LocalSplitters::Fixed A fixed size local splitter.
|
178
|
+
#
|
179
|
+
# @example Splitting in 4 even groups of two digits.
|
141
180
|
# match(/^(0\d{2})\d+$/) >> split(2,2,2,2) # If it matches, split in 4 groups of size 2.
|
142
181
|
#
|
143
182
|
def split *local
|
144
|
-
local << local.pop + 10 # Allow for call-through numbers with an arbitrary size.
|
183
|
+
# local << local.pop + 10 # Allow for call-through numbers with an arbitrary size.
|
145
184
|
LocalSplitters::Fixed.instance_for local
|
146
185
|
end
|
147
186
|
|
148
187
|
# Matches on the rest of the number and splits according
|
149
188
|
# to the given value for the regexp key.
|
150
189
|
#
|
151
|
-
#
|
152
|
-
#
|
190
|
+
# Also takes ranges.
|
191
|
+
#
|
192
|
+
# @param [Hash] options Can contain option :fallback A fallback amount of group sizes in case it doesn't match.
|
193
|
+
#
|
194
|
+
# @return LocalSplitters::Regex A regexp-based local splitter.
|
153
195
|
#
|
154
|
-
#
|
196
|
+
# @example Norway
|
155
197
|
# country '47',
|
156
198
|
# none >> matched_split(/^[1].*$/ => [3],
|
157
199
|
# /^[489].*$/ => [3,2,3],
|
158
200
|
# :fallback => [2,2,2,2])
|
159
201
|
#
|
160
202
|
def matched_split options = {}
|
161
|
-
|
203
|
+
LocalSplitters::Regex.instance_for options
|
162
204
|
end
|
163
205
|
|
164
206
|
# Validators
|
@@ -166,17 +208,20 @@ module Phony
|
|
166
208
|
|
167
209
|
# Which NDCs are explicitly invalid?
|
168
210
|
#
|
169
|
-
#
|
211
|
+
# @param [Regexp, String] ndc A regexp or a string of invalid NDCs.
|
170
212
|
#
|
171
|
-
#
|
213
|
+
# @return Validators::NDC An NDC validator
|
214
|
+
#
|
215
|
+
# @example NANP
|
172
216
|
# country '1',
|
173
217
|
# fixed(3, :zero => false) >> split(3,4),
|
174
218
|
# invalid_ndcs('911') # The regexp /911/ would also work.
|
175
219
|
#
|
176
|
-
def invalid_ndcs ndc
|
177
|
-
|
220
|
+
def invalid_ndcs *ndc
|
221
|
+
Validators::NDC.new invalid: ndc
|
178
222
|
end
|
179
223
|
|
224
|
+
|
180
225
|
end
|
181
226
|
|
182
227
|
end
|
@@ -27,7 +27,23 @@ module Phony
|
|
27
27
|
# The format [3, 2, 2] splits a number like '3332222' into ['333', '22', '22'].
|
28
28
|
#
|
29
29
|
def initialize format = nil
|
30
|
-
|
30
|
+
format = format && format.dup || [3, 2, 2]
|
31
|
+
@format, @length = extract_params format
|
32
|
+
@format << @format.pop + 10
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
#
|
37
|
+
def extract_params format
|
38
|
+
if format.last.respond_to? :max
|
39
|
+
last = format.pop
|
40
|
+
length = format.inject(0) { |total, part| total + part }
|
41
|
+
length = (length+last.min..length+last.max)
|
42
|
+
format << last.min
|
43
|
+
else
|
44
|
+
length = format.inject(0) { |total, part| total + part }
|
45
|
+
end
|
46
|
+
[format, length]
|
31
47
|
end
|
32
48
|
|
33
49
|
# Split a local number according to an assumed country specific format.
|
@@ -43,6 +59,14 @@ module Phony
|
|
43
59
|
end
|
44
60
|
end
|
45
61
|
|
62
|
+
#
|
63
|
+
#
|
64
|
+
def plausible? rest, hints = {}
|
65
|
+
return true if hints[:check_length] == false
|
66
|
+
|
67
|
+
@length === rest.inject(0) { |total, part| total + part.size }
|
68
|
+
end
|
69
|
+
|
46
70
|
end
|
47
71
|
|
48
72
|
end
|
@@ -42,6 +42,15 @@ module Phony
|
|
42
42
|
split_with number, fallback
|
43
43
|
end
|
44
44
|
|
45
|
+
def plausible? rest, hints = {}
|
46
|
+
number = rest.inject('', :+)
|
47
|
+
mapping.each do |regex, format|
|
48
|
+
next unless number =~ regex
|
49
|
+
return plausible_with? number, format
|
50
|
+
end
|
51
|
+
plausible_with? number, fallback
|
52
|
+
end
|
53
|
+
|
45
54
|
private
|
46
55
|
|
47
56
|
def split_with number, format
|
@@ -49,9 +58,14 @@ module Phony
|
|
49
58
|
result << number.slice!(0..size-1)
|
50
59
|
return result if number.empty?
|
51
60
|
result
|
52
|
-
end
|
61
|
+
end << number
|
53
62
|
end
|
54
|
-
|
63
|
+
|
64
|
+
def plausible_with? number, format
|
65
|
+
length = format.inject 0, :+
|
66
|
+
number.length == length
|
67
|
+
end
|
68
|
+
|
55
69
|
end
|
56
70
|
|
57
71
|
end
|
data/lib/phony/national_code.rb
CHANGED
@@ -3,13 +3,14 @@ module Phony
|
|
3
3
|
# NationalCodes have a special numbers splitter, a national code splitter and a local code splitter.
|
4
4
|
#
|
5
5
|
class NationalCode
|
6
|
-
|
6
|
+
|
7
|
+
attr_reader :local_splitter
|
8
|
+
|
7
9
|
#
|
8
10
|
#
|
9
|
-
def initialize national_splitter, local_splitter
|
11
|
+
def initialize national_splitter, local_splitter
|
10
12
|
@national_splitter = national_splitter
|
11
13
|
@local_splitter = local_splitter
|
12
|
-
@normalize = normalize != false
|
13
14
|
end
|
14
15
|
|
15
16
|
# Split gets a number without country code and splits it into
|
@@ -25,11 +26,10 @@ module Phony
|
|
25
26
|
#
|
26
27
|
# Note: Some cases, like Italy, don't remove the relative zero.
|
27
28
|
#
|
28
|
-
def normalize national_number
|
29
|
-
|
30
|
-
national_number.gsub(/^0+/, '')
|
29
|
+
def normalize national_number, options = {}
|
30
|
+
national_number.gsub(/\A0+/, EMPTY_STRING)
|
31
31
|
end
|
32
32
|
|
33
33
|
end
|
34
34
|
|
35
|
-
end
|
35
|
+
end
|
@@ -1,15 +1,47 @@
|
|
1
1
|
module Phony
|
2
2
|
|
3
3
|
module NationalSplitters
|
4
|
-
|
4
|
+
|
5
|
+
# TODO Default = Fixed.new(...)?
|
6
|
+
#
|
5
7
|
class Default < DSL
|
6
8
|
|
7
9
|
def self.instance_for
|
8
10
|
@instance ||= new
|
9
11
|
end
|
10
|
-
|
12
|
+
|
13
|
+
# "Splits" the national part of a phone number into a single piece.
|
14
|
+
#
|
15
|
+
# @param [String] national_number An national part of a number.
|
16
|
+
#
|
17
|
+
# @return [Array<String>] An Array with the given number part as its element.
|
18
|
+
#
|
19
|
+
# @example Split the national part of a Swiss number.
|
20
|
+
# Phony.split("1234567") # => ["1234567"]
|
21
|
+
#
|
11
22
|
def split national_number
|
12
|
-
[national_number]
|
23
|
+
[nil, national_number]
|
24
|
+
end
|
25
|
+
|
26
|
+
# By default, the national part of a number is always plausible.
|
27
|
+
#
|
28
|
+
# @param [String] rest An national part of a number (ignored).
|
29
|
+
# @param [Fixnum] size Size (ignored).
|
30
|
+
# @param [Hash] hints Hints (ignored).
|
31
|
+
#
|
32
|
+
# @return [Boolean] Always true.
|
33
|
+
#
|
34
|
+
# @example Split the national part of a Swiss number.
|
35
|
+
# Phony.plausible?("1234567") # => true
|
36
|
+
#
|
37
|
+
def plausible? rest, size, hints = {}
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
41
|
+
# A valid length (at least 3).
|
42
|
+
#
|
43
|
+
def length
|
44
|
+
3
|
13
45
|
end
|
14
46
|
|
15
47
|
end
|
@@ -9,15 +9,20 @@ module Phony
|
|
9
9
|
#
|
10
10
|
#
|
11
11
|
def >> local_splitter
|
12
|
-
country_for local_splitter
|
12
|
+
country_for local_splitter
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
#
|
16
|
+
#
|
17
|
+
def country_for local_splitter
|
18
|
+
Phony::Country.new Phony::NationalCode.new(self, local_splitter)
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO Remove?
|
22
|
+
#
|
23
|
+
def reserved
|
24
|
+
|
25
|
+
end
|
21
26
|
|
22
27
|
end
|
23
28
|
|
@@ -20,7 +20,7 @@ module Phony
|
|
20
20
|
|
21
21
|
def initialize size, options = {}
|
22
22
|
@size = size
|
23
|
-
@zero = options[:zero] == false ? nil : '0'
|
23
|
+
@zero = nil # options[:zero] == false ? nil : '0'
|
24
24
|
end
|
25
25
|
|
26
26
|
# Takes a national number and splits it into ndc and rest.
|
@@ -30,6 +30,12 @@ module Phony
|
|
30
30
|
[@zero, national_number.slice!(0...@size), national_number]
|
31
31
|
end
|
32
32
|
|
33
|
+
# A valid length.
|
34
|
+
#
|
35
|
+
def length
|
36
|
+
@size
|
37
|
+
end
|
38
|
+
|
33
39
|
end
|
34
40
|
|
35
41
|
end
|
@@ -31,14 +31,18 @@ module Phony
|
|
31
31
|
# since using nil is dangerous and breaks
|
32
32
|
# abstraction)
|
33
33
|
#
|
34
|
-
# Note:
|
35
|
-
#
|
36
|
-
# TODO Flip nil/false?
|
34
|
+
# Note: Decided it stays in. When formatting, it's turned into nil.
|
37
35
|
#
|
38
36
|
def split national_number
|
39
37
|
[nil, false, national_number]
|
40
38
|
end
|
41
39
|
|
40
|
+
# A valid length.
|
41
|
+
#
|
42
|
+
def length
|
43
|
+
0
|
44
|
+
end
|
45
|
+
|
42
46
|
end
|
43
47
|
|
44
48
|
end
|
@@ -18,17 +18,19 @@ module Phony
|
|
18
18
|
|
19
19
|
# Extract a starting point.
|
20
20
|
#
|
21
|
+
# This if can possibly be removed.
|
22
|
+
#
|
21
23
|
presumed_code = if @mapped_ndc_min_length > 0
|
22
|
-
national_number.slice!(0..@mapped_ndc_min_length-1)
|
24
|
+
presumed_code = national_number.slice!(0..@mapped_ndc_min_length-1)
|
23
25
|
else
|
24
26
|
''
|
25
27
|
end
|
26
28
|
|
27
29
|
# Try for all possible mapped.
|
28
30
|
#
|
29
|
-
@mapped_ndc_min_length.upto
|
30
|
-
|
31
|
-
return [@zero, presumed_code, national_number] unless
|
31
|
+
@mapped_ndc_min_length.upto @mapped_ndc_max_length do |i|
|
32
|
+
ndcs_of_size_i = @ndcs[i]
|
33
|
+
return [@zero, presumed_code, national_number] unless ndcs_of_size_i && !ndcs_of_size_i.include?(presumed_code)
|
32
34
|
presumed_code << national_number.slice!(0..0)
|
33
35
|
end
|
34
36
|
|
@@ -37,15 +39,17 @@ module Phony
|
|
37
39
|
super fallback_number
|
38
40
|
end
|
39
41
|
|
42
|
+
# A valid length.
|
43
|
+
#
|
44
|
+
def length
|
45
|
+
(@mapped_ndc_min_length..@mapped_ndc_max_length)
|
46
|
+
end
|
47
|
+
|
40
48
|
private
|
41
49
|
|
42
|
-
# def restructure ndc_map
|
43
|
-
# optimize ndc_map.values.flatten
|
44
|
-
# end
|
45
|
-
|
46
50
|
# Optimizes and restructures the given ndcs array.
|
47
51
|
#
|
48
|
-
def optimize
|
52
|
+
def optimize ndc_ary
|
49
53
|
ndcs = {}
|
50
54
|
ndc_ary.each do |ndc|
|
51
55
|
ndcs[ndc.length] ||= []
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Phony
|
2
|
+
|
3
|
+
class TrunkCode
|
4
|
+
|
5
|
+
# Parameters:
|
6
|
+
# * code: The trunk code, e.g. 0.
|
7
|
+
#
|
8
|
+
# Options:
|
9
|
+
# * normalize: [true (default), false] Remove the trunk code when normalizing (only use if number scheme is defined unambiguously).
|
10
|
+
# * split: [true, false (default)] Remove the trunk code when splitting (only use if number scheme is defined unambiguously).
|
11
|
+
# * format: [true (default), false] Add the trunk code when formatting (passing `false` will not add it).
|
12
|
+
#
|
13
|
+
def initialize code, options = {}
|
14
|
+
@code = code
|
15
|
+
@trunk_code_replacement = /\A#{code.gsub(%r{%s}, '')}/
|
16
|
+
@normalize = options[:normalize] || options[:normalize].nil?
|
17
|
+
@split = options[:split]
|
18
|
+
@format = options[:format] || options[:format].nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
# Prepends itself to the other codes.
|
22
|
+
#
|
23
|
+
def | other
|
24
|
+
other.codes.unshift self
|
25
|
+
other
|
26
|
+
end
|
27
|
+
|
28
|
+
# Split gets a number without country code and splits it into
|
29
|
+
# its parts.
|
30
|
+
#
|
31
|
+
def split national_number
|
32
|
+
national_number.gsub! @trunk_code_replacement, EMPTY_STRING if @split
|
33
|
+
return [self, national_number]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Normalize normalizes the given national number.
|
37
|
+
#
|
38
|
+
def normalize national_number, options = {}
|
39
|
+
national_number.gsub! @trunk_code_replacement, EMPTY_STRING if @normalize && options[:cc]
|
40
|
+
return national_number
|
41
|
+
end
|
42
|
+
|
43
|
+
# Format the trunk code using the spaces given.
|
44
|
+
#
|
45
|
+
def format space, force = nil
|
46
|
+
if force || @format
|
47
|
+
if @code.size > 1
|
48
|
+
(@code % space).gsub(/\D/, ' ')
|
49
|
+
else
|
50
|
+
@code
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
data/lib/phony/vanity.rb
CHANGED
@@ -16,11 +16,11 @@ module Phony
|
|
16
16
|
# Replaces (and normalizes) vanity characters of passed number with correct digits.
|
17
17
|
#
|
18
18
|
def self.replace number
|
19
|
-
number.tr
|
19
|
+
number.tr(*mapping)
|
20
20
|
end
|
21
21
|
|
22
22
|
# Returns true if there is a character in the number
|
23
|
-
# after the first
|
23
|
+
# after the first three numbers.
|
24
24
|
#
|
25
25
|
@@vanity_regexp = /\A\d{3}[a-zA-Z]{6,12}\Z/
|
26
26
|
def self.vanity? number
|
@@ -29,7 +29,7 @@ module Phony
|
|
29
29
|
|
30
30
|
# Vanity-Normalized.
|
31
31
|
#
|
32
|
-
@@vanity_normalizing_regexp = /^0*|[^\
|
32
|
+
@@vanity_normalizing_regexp = /^0*|[^\w]/
|
33
33
|
def self.normalized number
|
34
34
|
number.gsub @@vanity_normalizing_regexp, ''
|
35
35
|
end
|