phony 2.15.0 → 2.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.textile +35 -7
- data/lib/phony/config.rb +91 -0
- data/lib/phony/countries/argentina.rb +355 -0
- data/lib/phony/countries/austria.rb +34 -24
- data/lib/phony/countries/bangladesh.rb +2 -0
- data/lib/phony/countries/belarus.rb +2 -0
- data/lib/phony/countries/brazil.rb +6 -4
- data/lib/phony/countries/cambodia.rb +6 -4
- data/lib/phony/countries/china.rb +7 -2
- data/lib/phony/countries/croatia.rb +13 -16
- data/lib/phony/countries/georgia.rb +6 -4
- data/lib/phony/countries/germany.rb +5 -2
- data/lib/phony/countries/guinea.rb +8 -5
- data/lib/phony/countries/india.rb +2 -0
- data/lib/phony/countries/indonesia.rb +8 -3
- data/lib/phony/countries/ireland.rb +27 -23
- data/lib/phony/countries/italy.rb +30 -17
- data/lib/phony/countries/japan.rb +61 -8
- data/lib/phony/countries/kyrgyzstan.rb +2 -0
- data/lib/phony/countries/latvia.rb +2 -0
- data/lib/phony/countries/libya.rb +3 -1
- data/lib/phony/countries/malaysia.rb +22 -2
- data/lib/phony/countries/moldova.rb +2 -0
- data/lib/phony/countries/montenegro.rb +2 -0
- data/lib/phony/countries/myanmar.rb +2 -0
- data/lib/phony/countries/namibia.rb +2 -0
- data/lib/phony/countries/nepal.rb +2 -0
- data/lib/phony/countries/netherlands.rb +5 -1
- data/lib/phony/countries/pakistan.rb +2 -0
- data/lib/phony/countries/paraguay.rb +2 -0
- data/lib/phony/countries/russia_kazakhstan_abkhasia_south_ossetia.rb +24 -14
- data/lib/phony/countries/saudi_arabia.rb +40 -0
- data/lib/phony/countries/serbia.rb +10 -4
- data/lib/phony/countries/somalia.rb +5 -1
- data/lib/phony/countries/south_korea.rb +16 -9
- data/lib/phony/countries/sweden.rb +53 -38
- data/lib/phony/countries/taiwan.rb +22 -46
- data/lib/phony/countries/tajikistan.rb +2 -0
- data/lib/phony/countries/turkmenistan.rb +2 -0
- data/lib/phony/countries/ukraine.rb +5 -2
- data/lib/phony/countries/united_kingdom.rb +5 -2
- data/lib/phony/countries/uruguay.rb +2 -0
- data/lib/phony/countries/vietnam.rb +94 -92
- data/lib/phony/countries/zimbabwe.rb +2 -0
- data/lib/phony/countries.rb +210 -98
- data/lib/phony/country.rb +15 -3
- data/lib/phony/country_codes.rb +17 -4
- data/lib/phony/dsl.rb +5 -3
- data/lib/phony/local_splitters/fixed.rb +2 -0
- data/lib/phony/national_code.rb +1 -1
- data/lib/phony/national_splitters/none.rb +1 -3
- data/lib/phony/trunk_code.rb +5 -4
- data/lib/phony/vanity.rb +1 -1
- data/lib/phony.rb +94 -59
- data/spec/functional/config_spec.rb +44 -0
- data/spec/functional/plausibility_spec.rb +373 -35
- data/spec/lib/phony/countries_spec.rb +295 -63
- data/spec/lib/phony/country_codes_spec.rb +106 -33
- data/spec/lib/phony/country_spec.rb +54 -15
- data/spec/lib/phony/dsl_spec.rb +2 -2
- data/spec/lib/phony/local_splitters/regex_spec.rb +12 -5
- data/spec/lib/phony/national_splitters/default_spec.rb +1 -1
- data/spec/lib/phony/trunk_code_spec.rb +85 -0
- data/spec/lib/phony/vanity_spec.rb +30 -0
- data/spec/lib/phony_spec.rb +70 -0
- metadata +27 -17
data/lib/phony/country_codes.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Phony
|
2
2
|
|
3
|
-
EMPTY_STRING = ''
|
3
|
+
EMPTY_STRING = '' unless defined?(EMPTY_STRING)
|
4
4
|
|
5
5
|
# Handles determining the correct national code handler.
|
6
6
|
#
|
@@ -66,7 +66,7 @@ module Phony
|
|
66
66
|
country, cc, number = partial_split number
|
67
67
|
country
|
68
68
|
end
|
69
|
-
number = country.normalize number
|
69
|
+
number = country.normalize number, cc: cc
|
70
70
|
countrify! number, cc
|
71
71
|
end
|
72
72
|
|
@@ -77,7 +77,7 @@ module Phony
|
|
77
77
|
country, cc, national_number = partial_split number
|
78
78
|
|
79
79
|
# Split the national number into ndc and local part.
|
80
|
-
|
80
|
+
_, ndc, *local = country.split national_number
|
81
81
|
|
82
82
|
[cc, ndc, *local]
|
83
83
|
end
|
@@ -97,9 +97,20 @@ module Phony
|
|
97
97
|
|
98
98
|
# False if it fails the basic check.
|
99
99
|
#
|
100
|
-
return false unless (4..
|
100
|
+
return false unless (4..16) === normalized.size # unless hints[:check_length] == false
|
101
101
|
|
102
102
|
country, cc, rest = partial_split normalized
|
103
|
+
|
104
|
+
# Was a country calling code given?
|
105
|
+
#
|
106
|
+
if ccc = hints[:ccc]
|
107
|
+
cc, ndc, *local = split ccc
|
108
|
+
|
109
|
+
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
|
+
hints[:cc] = cc
|
112
|
+
hints[:ndc] = ndc
|
113
|
+
end
|
103
114
|
|
104
115
|
# Country code plausible?
|
105
116
|
#
|
@@ -109,6 +120,8 @@ module Phony
|
|
109
120
|
# Country specific tests.
|
110
121
|
#
|
111
122
|
country.plausible? rest, hints
|
123
|
+
rescue ArgumentError
|
124
|
+
raise
|
112
125
|
rescue StandardError
|
113
126
|
return false
|
114
127
|
end
|
data/lib/phony/dsl.rb
CHANGED
@@ -12,9 +12,9 @@ module Phony
|
|
12
12
|
#
|
13
13
|
# Phony.define.country ...
|
14
14
|
#
|
15
|
-
def self.define
|
15
|
+
def self.define(&block)
|
16
16
|
dsl = DSL.new
|
17
|
-
dsl.instance_eval(&
|
17
|
+
dsl.instance_eval(&block) if block_given?
|
18
18
|
dsl
|
19
19
|
end
|
20
20
|
|
@@ -41,6 +41,8 @@ module Phony
|
|
41
41
|
# country '27', # CC, followed by rules, for example fixed(2) >> ...
|
42
42
|
#
|
43
43
|
def country country_code, definition, options = {}
|
44
|
+
return unless Phony.config.load?(country_code)
|
45
|
+
|
44
46
|
definition.with country_code, options
|
45
47
|
Phony::CountryCodes.instance.add country_code, definition
|
46
48
|
end
|
@@ -139,7 +141,7 @@ module Phony
|
|
139
141
|
#
|
140
142
|
ndcs = ndcs.first if Array === ndcs.first
|
141
143
|
|
142
|
-
NationalSplitters::Variable.new options[:max_length], ndcs
|
144
|
+
NationalSplitters::Variable.new options[:max_length], ndcs.map(&:freeze)
|
143
145
|
end
|
144
146
|
|
145
147
|
# If you have a number of (possibly) variable length NDCs
|
data/lib/phony/national_code.rb
CHANGED
@@ -31,9 +31,7 @@ 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]
|
data/lib/phony/trunk_code.rb
CHANGED
@@ -6,8 +6,9 @@ module Phony
|
|
6
6
|
# * code: The trunk code, e.g. 0.
|
7
7
|
#
|
8
8
|
# Options:
|
9
|
-
# * normalize: Remove the trunk code when normalizing (only use if number scheme is defined unambiguously).
|
10
|
-
# * split: Remove the trunk code when splitting (only use if number scheme is defined unambiguously).
|
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).
|
11
12
|
#
|
12
13
|
def initialize code, options = {}
|
13
14
|
@code = code
|
@@ -34,8 +35,8 @@ module Phony
|
|
34
35
|
|
35
36
|
# Normalize normalizes the given national number.
|
36
37
|
#
|
37
|
-
def normalize national_number
|
38
|
-
national_number.gsub! @trunk_code_replacement, EMPTY_STRING if @normalize
|
38
|
+
def normalize national_number, options = {}
|
39
|
+
national_number.gsub! @trunk_code_replacement, EMPTY_STRING if @normalize && options[:cc]
|
39
40
|
return national_number
|
40
41
|
end
|
41
42
|
|
data/lib/phony/vanity.rb
CHANGED
data/lib/phony.rb
CHANGED
@@ -1,69 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE We use Kernel.load here, as it's possible to redefine Phony via Phony::Config.
|
4
|
+
|
1
5
|
# Framework.
|
2
6
|
#
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
7
|
+
load File.expand_path '../phony/config.rb', __FILE__
|
8
|
+
load File.expand_path '../phony/vanity.rb', __FILE__
|
9
|
+
load File.expand_path '../phony/local_splitters/fixed.rb', __FILE__
|
10
|
+
load File.expand_path '../phony/local_splitters/regex.rb', __FILE__
|
11
|
+
load File.expand_path '../phony/national_splitters/dsl.rb', __FILE__
|
12
|
+
load File.expand_path '../phony/national_splitters/fixed.rb', __FILE__
|
13
|
+
load File.expand_path '../phony/national_splitters/variable.rb', __FILE__
|
14
|
+
load File.expand_path '../phony/national_splitters/regex.rb', __FILE__
|
15
|
+
load File.expand_path '../phony/national_splitters/default.rb', __FILE__
|
16
|
+
load File.expand_path '../phony/national_splitters/none.rb', __FILE__
|
17
|
+
load File.expand_path '../phony/national_code.rb', __FILE__
|
18
|
+
load File.expand_path '../phony/country.rb', __FILE__
|
19
|
+
load File.expand_path '../phony/trunk_code.rb', __FILE__
|
20
|
+
load File.expand_path '../phony/country_codes.rb', __FILE__
|
21
|
+
load File.expand_path '../phony/dsl.rb', __FILE__
|
18
22
|
|
19
23
|
# Countries.
|
20
24
|
#
|
21
25
|
# The ones that need more space to define.
|
22
26
|
#
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
27
|
+
load File.expand_path '../phony/countries/argentina.rb', __FILE__
|
28
|
+
load File.expand_path '../phony/countries/austria.rb', __FILE__
|
29
|
+
load File.expand_path '../phony/countries/bangladesh.rb', __FILE__
|
30
|
+
load File.expand_path '../phony/countries/belarus.rb', __FILE__
|
31
|
+
load File.expand_path '../phony/countries/brazil.rb', __FILE__
|
32
|
+
load File.expand_path '../phony/countries/cambodia.rb', __FILE__
|
33
|
+
load File.expand_path '../phony/countries/croatia.rb', __FILE__
|
34
|
+
load File.expand_path '../phony/countries/china.rb', __FILE__
|
35
|
+
load File.expand_path '../phony/countries/georgia.rb', __FILE__
|
36
|
+
load File.expand_path '../phony/countries/germany.rb', __FILE__
|
37
|
+
load File.expand_path '../phony/countries/guinea.rb', __FILE__
|
38
|
+
load File.expand_path '../phony/countries/india.rb', __FILE__
|
39
|
+
load File.expand_path '../phony/countries/indonesia.rb', __FILE__
|
40
|
+
load File.expand_path '../phony/countries/ireland.rb', __FILE__
|
41
|
+
load File.expand_path '../phony/countries/italy.rb', __FILE__
|
42
|
+
load File.expand_path '../phony/countries/japan.rb', __FILE__
|
43
|
+
load File.expand_path '../phony/countries/kyrgyzstan.rb', __FILE__
|
44
|
+
load File.expand_path '../phony/countries/latvia.rb', __FILE__
|
45
|
+
load File.expand_path '../phony/countries/libya.rb', __FILE__
|
46
|
+
load File.expand_path '../phony/countries/malaysia.rb', __FILE__
|
47
|
+
load File.expand_path '../phony/countries/moldova.rb', __FILE__
|
48
|
+
load File.expand_path '../phony/countries/montenegro.rb', __FILE__
|
49
|
+
load File.expand_path '../phony/countries/myanmar.rb', __FILE__
|
50
|
+
load File.expand_path '../phony/countries/namibia.rb', __FILE__
|
51
|
+
load File.expand_path '../phony/countries/nepal.rb', __FILE__
|
52
|
+
load File.expand_path '../phony/countries/netherlands.rb', __FILE__
|
53
|
+
load File.expand_path '../phony/countries/pakistan.rb', __FILE__
|
54
|
+
load File.expand_path '../phony/countries/paraguay.rb', __FILE__
|
55
|
+
load File.expand_path '../phony/countries/russia_kazakhstan_abkhasia_south_ossetia.rb', __FILE__
|
56
|
+
load File.expand_path '../phony/countries/saudi_arabia.rb', __FILE__
|
57
|
+
load File.expand_path '../phony/countries/serbia.rb', __FILE__
|
58
|
+
load File.expand_path '../phony/countries/somalia.rb', __FILE__
|
59
|
+
load File.expand_path '../phony/countries/south_korea.rb', __FILE__
|
60
|
+
load File.expand_path '../phony/countries/sweden.rb', __FILE__
|
61
|
+
load File.expand_path '../phony/countries/taiwan.rb', __FILE__
|
62
|
+
load File.expand_path '../phony/countries/tajikistan.rb', __FILE__
|
63
|
+
load File.expand_path '../phony/countries/turkmenistan.rb', __FILE__
|
64
|
+
load File.expand_path '../phony/countries/vietnam.rb', __FILE__
|
65
|
+
load File.expand_path '../phony/countries/ukraine.rb', __FILE__
|
66
|
+
load File.expand_path '../phony/countries/united_kingdom.rb', __FILE__
|
67
|
+
load File.expand_path '../phony/countries/uruguay.rb', __FILE__
|
68
|
+
load File.expand_path '../phony/countries/zimbabwe.rb', __FILE__
|
63
69
|
|
64
70
|
# All other countries.
|
65
71
|
#
|
66
|
-
|
72
|
+
load File.expand_path '../phony/countries.rb', __FILE__
|
67
73
|
|
68
74
|
# Phony is the main module and is generally used to process
|
69
75
|
# E164 phone numbers directly.
|
@@ -75,11 +81,33 @@ module Phony
|
|
75
81
|
# @example
|
76
82
|
# Phony.normalize("Fnork!") # Raises a Phony::NormalizationError.
|
77
83
|
#
|
78
|
-
class NormalizationError <
|
84
|
+
class NormalizationError < ArgumentError
|
79
85
|
def initialize
|
80
86
|
super %Q{Phony could not normalize the given number. Is it a phone number?}
|
81
87
|
end
|
82
88
|
end
|
89
|
+
|
90
|
+
# Raised in case Phony can't split a given number.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# Phony.split("Fnork!") # Raises a Phony::SplittingError.
|
94
|
+
#
|
95
|
+
class SplittingError < ArgumentError
|
96
|
+
def initialize number
|
97
|
+
super %Q{Phony could not split the given number. Is #{(number.nil? || number == '') ? 'it' : number.inspect} a phone number?}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Raised in case Phony can't format a given number.
|
102
|
+
#
|
103
|
+
# @example
|
104
|
+
# Phony.format("Fnork!") # Raises a Phony::FormattingError.
|
105
|
+
#
|
106
|
+
class FormattingError < ArgumentError
|
107
|
+
def initialize
|
108
|
+
super %Q{Phony could not format the given number. Is it a phone number?}
|
109
|
+
end
|
110
|
+
end
|
83
111
|
|
84
112
|
# Phony uses a single country codes instance.
|
85
113
|
#
|
@@ -120,6 +148,7 @@ module Phony
|
|
120
148
|
#
|
121
149
|
def normalize phone_number, options = {}
|
122
150
|
raise ArgumentError, "Phone number cannot be nil. Use e.g. number && Phony.normalize(number)." unless phone_number
|
151
|
+
|
123
152
|
normalize! phone_number.dup, options
|
124
153
|
end
|
125
154
|
# A destructive version of {#normalize}.
|
@@ -161,7 +190,8 @@ module Phony
|
|
161
190
|
#
|
162
191
|
def split phone_number
|
163
192
|
raise ArgumentError, "Phone number cannot be nil. Use e.g. number && Phony.split(number)." unless phone_number
|
164
|
-
|
193
|
+
|
194
|
+
split! phone_number.dup, phone_number
|
165
195
|
end
|
166
196
|
# A destructive version of {#split}.
|
167
197
|
#
|
@@ -177,8 +207,11 @@ module Phony
|
|
177
207
|
# @example Split a NANP number.
|
178
208
|
# Phony.split!("13015550100") # => ["1", "301", "555", "0100"]
|
179
209
|
#
|
180
|
-
def split! phone_number
|
210
|
+
def split! phone_number, error_number = nil
|
181
211
|
@codes.split phone_number
|
212
|
+
rescue
|
213
|
+
# NB The error_number (reference) is used because phone_number is destructively handled.
|
214
|
+
raise SplittingError.new(error_number)
|
182
215
|
end
|
183
216
|
|
184
217
|
# Formats a normalized E164 number according to a country's formatting scheme.
|
@@ -230,6 +263,8 @@ module Phony
|
|
230
263
|
#
|
231
264
|
def format! phone_number, options = {}
|
232
265
|
@codes.format phone_number, options
|
266
|
+
rescue
|
267
|
+
raise FormattingError.new
|
233
268
|
end
|
234
269
|
alias formatted format
|
235
270
|
alias formatted! format!
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
describe 'Phony::Config' do
|
4
|
+
describe 'load' do
|
5
|
+
before do
|
6
|
+
# NOTE We redefine Phony as if it was not loaded for this set of tests.
|
7
|
+
Object.__send__(:remove_const, :Phony) if Object.constants.include?(:Phony)
|
8
|
+
|
9
|
+
load 'phony/config.rb'
|
10
|
+
end
|
11
|
+
after(:all) do
|
12
|
+
# After running this suite, we load all of Phony for the following tests.
|
13
|
+
load 'phony/config.rb'
|
14
|
+
|
15
|
+
Phony::Config.load
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not fail when loading all' do
|
19
|
+
Phony::Config.load
|
20
|
+
|
21
|
+
Phony.split('15551115511').should == ['1', '555', '111', '5511']
|
22
|
+
end
|
23
|
+
it 'raises when a CC is used that has not been loaded.' do
|
24
|
+
Phony::Config.load('41')
|
25
|
+
|
26
|
+
expect { Phony.split('15551115511') }.to raise_error
|
27
|
+
end
|
28
|
+
it 'raises when a CC is used that has not been loaded.' do
|
29
|
+
Phony::Config.load(only: ['41'])
|
30
|
+
|
31
|
+
expect { Phony.split('15551115511') }.to raise_error
|
32
|
+
end
|
33
|
+
it 'raises when a CC is used that has not been loaded.' do
|
34
|
+
Phony::Config.load(except: ['1'])
|
35
|
+
|
36
|
+
expect { Phony.split('15551115511') }.to raise_error
|
37
|
+
end
|
38
|
+
it 'does not raise when a CC is used that has been loaded.' do
|
39
|
+
Phony::Config.load(except: ['41'])
|
40
|
+
|
41
|
+
Phony.split('15551115511').should == ['1', '555', '111', '5511']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|