phonelib 0.10.3 → 0.10.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9fe27c3c85d76103dc9fe5fe1a3877f31fd06cf6b3327b25d4f93aea3238ca63
4
- data.tar.gz: 15b2fb31d0e9997d0ef6fef3502a15499d8bd151a05f8ffd6ef08c23729db121
3
+ metadata.gz: 31ced2b5e00ea0e8386738b673cf28bdebd710f92d2f2581b17e41ddfb78714f
4
+ data.tar.gz: c713179d0c186a4595dc0927ce214fb3b4eee080bcdba01d97e4d08d58fbe2d7
5
5
  SHA512:
6
- metadata.gz: 585a0298a4ec578788d3ee34d4c8c567290b9734f051a7bb73e85515b33b54c37792757d91a1c07fead6c9473bc6c5b9913c3313dc45fee03ea5e27e8152adda
7
- data.tar.gz: 715cf0441e86fa0d3f8522023ace36fb3fe367e1c84c373d88130d87a8e51d8c8ed40bc17830d875d9c0f3b79d42ca81f3032106dce3964fc88ac3397c369d97
6
+ metadata.gz: 2e9de11fcf90df49c042ae6e2d443b7f83cb0189fe06629d28fa0e76cbbba499c442db2d2cb8af90b9819024f20cda8d30bd09f8858a7f4111599dd177dff998
7
+ data.tar.gz: 8cc3662ab6f37b380eb8046876e7ada3e547a48a226105ee852f3b803d319f3defd9f59f912191fc18c6cc53b0899b556a72491677de8e1bcb97bc6f73a15946
data/README.md CHANGED
@@ -13,7 +13,7 @@ But it still doesn't include all Google's library functionality.
13
13
 
14
14
  ## Incorrect parsing or validation
15
15
 
16
- In case your phone number is incorrectly parsed, you can check original libphonenumber for result [here](https://rawgit.com/googlei18n/libphonenumber/master/javascript/i18n/phonenumbers/demo-compiled.html) and in case of same parse result [open an issue for them](https://issuetracker.google.com/issues/new?component=192347&template=829703). This gem's data is based on it.
16
+ In case your phone number is incorrectly parsed, you can check original libphonenumber for result [here](https://htmlpreview.github.io/?https://github.com/google/libphonenumber/blob/master/javascript/i18n/phonenumbers/demo-compiled.html) and in case of same parse result [open an issue for them](http://issuetracker.google.com/issues/new?component=192347). This gem's data is based on it.
17
17
  If you can't wait for libphonenumber to resolve the issue, try to use ```Phonelib.add_additional_regex``` and ```Phonelib.additional_regexes``` methods.
18
18
 
19
19
  ## Information
Binary file
data/data/phone_data.dat CHANGED
Binary file
data/lib/phonelib/core.rb CHANGED
@@ -202,7 +202,7 @@ module Phonelib
202
202
  end
203
203
 
204
204
  def add_additional_regex(country, type, national_regex)
205
- return unless Phonelib::Core::TYPES_DESC.keys.include?(type.to_sym)
205
+ return unless Phonelib::Core::TYPES_DESC.key?(type.to_sym)
206
206
  return unless national_regex.is_a?(String)
207
207
  @@phone_data = @@data_by_country_codes = nil
208
208
  @@additional_regexes[country.to_s.upcase] ||= {}
@@ -381,6 +381,7 @@ module Phonelib
381
381
  carrier_selection_codes: 'Carrier Selection codes',
382
382
  area_code_optional: 'Are code optional'
383
383
  }.freeze
384
+ TYPES_DESC_KEYS = TYPES_DESC.keys.freeze
384
385
 
385
386
  # @private short codes types keys
386
387
  SHORT_CODES = [
@@ -407,6 +408,13 @@ module Phonelib
407
408
  # @private Extended data key for carrier in prefixes hash
408
409
  EXT_CARRIER_KEY = :c
409
410
 
411
+ # @private Static arrays used to avoid allocations
412
+ FIXED_OR_MOBILE_ARRAY = [Core::FIXED_OR_MOBILE].freeze
413
+ FIXED_LINE_OR_MOBILE_ARRAY = [Core::FIXED_LINE, Core::MOBILE].freeze
414
+ POSSIBLE_VALID_ARRAY = [:possible, :valid].freeze
415
+ VALID_POSSIBLE_ARRAY = [:valid, :possible].freeze
416
+ NIL_RESULT_ARRAY = [nil, nil].freeze
417
+
410
418
  # method for parsing phone number.
411
419
  # On first run fills @@phone_data with data present in yaml file
412
420
  # @param phone [String] the phone number to be parsed
@@ -103,7 +103,13 @@ module Phonelib
103
103
  line = str_clean line, false
104
104
  next if line.empty? || line[0] == '#'
105
105
  prefix, line_data = line.split('|')
106
- data[prefix] = line_data && line_data.strip.split('&')
106
+ if line_data
107
+ data[prefix] = if line_data.strip =~ /[^ ]{3,}&[^ ]{3,}/
108
+ line_data.strip.split('&')
109
+ else
110
+ line_data.strip
111
+ end
112
+ end
107
113
  end
108
114
  data
109
115
  end
@@ -33,7 +33,7 @@ module Phonelib
33
33
 
34
34
  # pick best result when several countries specified
35
35
  def pick_results(results)
36
- [:valid, :possible].each do |key|
36
+ Core::VALID_POSSIBLE_ARRAY.each do |key|
37
37
  final = results.select { |_k, v| v[key].any? }
38
38
  return decorate_analyze_result(final) if final.size > 0
39
39
  end
@@ -69,9 +69,15 @@ module Phonelib
69
69
  end
70
70
 
71
71
  # replacing national prefix to simplified format
72
- def with_replaced_national_prefix(phone, data)
73
- return phone unless data[Core::NATIONAL_PREFIX_TRANSFORM_RULE]
74
- phone = phone.gsub(/^#{data[Core::COUNTRY_CODE]}/, '') if phone.start_with?(data[Core::COUNTRY_CODE]) && !data[Core::DOUBLE_COUNTRY_PREFIX_FLAG]
72
+ def with_replaced_national_prefix(passed_phone, data)
73
+ return passed_phone unless data[Core::NATIONAL_PREFIX_TRANSFORM_RULE]
74
+ phone = if passed_phone.start_with?(data[Core::COUNTRY_CODE]) && !data[Core::DOUBLE_COUNTRY_PREFIX_FLAG]
75
+ passed_phone.delete_prefix(data[Core::COUNTRY_CODE])
76
+ else
77
+ passed_phone
78
+ end
79
+ return passed_phone unless phone.match? cr("^#{type_regex(data[Core::TYPES][Core::GENERAL], Core::POSSIBLE_PATTERN)}$")
80
+
75
81
  pattern = cr("^(?:#{data[Core::NATIONAL_PREFIX_FOR_PARSING]})")
76
82
  match = phone.match pattern
77
83
  if match && match.captures.compact.size > 0
@@ -132,7 +138,10 @@ module Phonelib
132
138
  countries_data.each_with_object({}) do |data, result|
133
139
  key = data[:id]
134
140
  parsed = parse_single_country(phone, data)
135
- parsed = parse_single_country(with_replaced_national_prefix(phone, data), data) unless parsed && parsed[key] && parsed[key][:valid].size > 0
141
+ unless parsed && parsed[key] && parsed[key][:valid].size > 0
142
+ replaced_parsed = parse_single_country(with_replaced_national_prefix(phone, data), data)
143
+ parsed = replaced_parsed unless replaced_parsed.nil?
144
+ end
136
145
  if (!Phonelib.strict_double_prefix_check || key == country) && double_prefix_allowed?(data, phone, parsed && parsed[key])
137
146
  parsed2 = parse_single_country(changed_dp_phone(key, phone), data)
138
147
  parsed = parsed2 if parsed2 && parsed2[key] && parsed2[key][:valid].size > 0
@@ -153,13 +162,13 @@ module Phonelib
153
162
  # * +phone+ - phone number for parsing
154
163
  # * +data+ - country data to be based on for creating e164 representation
155
164
  def convert_to_e164(phone, data)
156
- match = phone.match full_regex_for_data(data, Core::VALID_PATTERN, !original_starts_with_plus?)
165
+ match = phone.match full_regex_for_data(data, Core::VALID_PATTERN, !original_starts_with_plus_or_double_zero?)
157
166
  case
158
167
  when match
159
168
  "#{data[Core::COUNTRY_CODE]}#{match.to_a.last}"
160
169
  when phone.match(cr("^#{data[Core::INTERNATIONAL_PREFIX]}"))
161
170
  phone.sub(cr("^#{data[Core::INTERNATIONAL_PREFIX]}"), Core::PLUS_SIGN)
162
- when original_starts_with_plus? && phone.start_with?(data[Core::COUNTRY_CODE])
171
+ when original_starts_with_plus_or_double_zero? && phone.start_with?(data[Core::COUNTRY_CODE])
163
172
  phone
164
173
  else
165
174
  "#{data[Core::COUNTRY_CODE]}#{phone}"
@@ -179,7 +188,7 @@ module Phonelib
179
188
  if Phonelib.additional_regexes.is_a?(Hash) && Phonelib.additional_regexes[data[:id]]
180
189
  index = Phonelib.additional_regexes[data[:id]].values.flatten.join('|').scan(/\(/).size
181
190
  end
182
- phone = country_match.to_a[-1 - index]
191
+ phone = country_match[-1 - index]
183
192
  result[:national] = phone
184
193
  result[:format] = number_format(phone, data[Core::FORMATS])
185
194
  result.merge! all_number_types(phone, data[Core::TYPES], not_valid)
@@ -220,7 +229,7 @@ module Phonelib
220
229
  def number_format(national, format_data)
221
230
  format_data && format_data.find do |format|
222
231
  (format[Core::LEADING_DIGITS].nil? || \
223
- national.match(cr("^(#{format[Core::LEADING_DIGITS]})"))) && \
232
+ national.match?(cr("^(#{format[Core::LEADING_DIGITS]})"))) && \
224
233
  national.match(cr("^(#{format[Core::PATTERN]})$"))
225
234
  end || Core::DEFAULT_NUMBER_FORMAT
226
235
  end
@@ -241,7 +250,7 @@ module Phonelib
241
250
  type_regex(patterns, Core::VALID_PATTERN)
242
251
  ]
243
252
  else
244
- [nil, nil]
253
+ Core::NIL_RESULT_ARRAY
245
254
  end
246
255
  end
247
256
  end
@@ -16,8 +16,8 @@ module Phonelib
16
16
  end
17
17
  end
18
18
 
19
- def original_starts_with_plus?
20
- original_s[0] == Core::PLUS_SIGN
19
+ def original_starts_with_plus_or_double_zero?
20
+ original_s[0] == Core::PLUS_SIGN || original_s[0..1] == '00'
21
21
  end
22
22
 
23
23
  # converts symbols in phone to numbers
@@ -61,7 +61,8 @@ module Phonelib
61
61
  def country_can_dp?(country)
62
62
  Phonelib.phone_data[country] &&
63
63
  Phonelib.phone_data[country][Core::DOUBLE_COUNTRY_PREFIX_FLAG] &&
64
- !original_starts_with_plus? && original_s.start_with?(Phonelib.phone_data[country][Core::COUNTRY_CODE])
64
+ !original_starts_with_plus_or_double_zero? &&
65
+ original_s.start_with?(Phonelib.phone_data[country][Core::COUNTRY_CODE])
65
66
  end
66
67
 
67
68
  # changes phone to with/without double country prefix
@@ -89,7 +90,7 @@ module Phonelib
89
90
  data[Core::DOUBLE_COUNTRY_PREFIX_FLAG] &&
90
91
  phone =~ cr("^#{data[Core::COUNTRY_CODE]}") &&
91
92
  parsed && (parsed[:valid].nil? || parsed[:valid].empty?) &&
92
- !original_starts_with_plus?
93
+ !original_starts_with_plus_or_double_zero?
93
94
  end
94
95
 
95
96
  # Returns original number passed if it's a string or empty string otherwise
@@ -103,7 +104,8 @@ module Phonelib
103
104
  #
104
105
  # * +country+ - country passed for parsing
105
106
  def country_or_default_country(country)
106
- country ||= (original_starts_with_plus? ? nil : Phonelib.default_country)
107
+ country ||= (original_starts_with_plus_or_double_zero? ? nil : Phonelib.default_country)
108
+
107
109
  if country.is_a?(Array)
108
110
  country.compact.map { |e| e.to_s.upcase }
109
111
  else
@@ -119,14 +121,15 @@ module Phonelib
119
121
  # * +data+ - country data hash
120
122
  # * +country_optional+ - whether to put country code as optional group
121
123
  def full_regex_for_data(data, type, country_optional = true)
122
- regex = []
123
- regex << '0{2}?'
124
- regex << "(#{data[Core::INTERNATIONAL_PREFIX]})?"
125
- regex << "(#{data[Core::COUNTRY_CODE]})#{country_optional ? '?' : ''}"
126
- regex << "(#{data[Core::NATIONAL_PREFIX_FOR_PARSING] || data[Core::NATIONAL_PREFIX]})?"
127
- regex << "(#{type_regex(data[Core::TYPES][Core::GENERAL], type)})" if data[Core::TYPES]
124
+ regex = +"^0{2}?(#{data[Core::INTERNATIONAL_PREFIX]})?(#{data[Core::COUNTRY_CODE]})#{country_optional ? '?' : ''}(#{data[Core::NATIONAL_PREFIX_FOR_PARSING] || data[Core::NATIONAL_PREFIX]})?"
125
+ if data[Core::TYPES]
126
+ regex << "("
127
+ regex << type_regex(data[Core::TYPES][Core::GENERAL], type)
128
+ regex << ")"
129
+ end
130
+ regex << "$"
128
131
 
129
- cr("^#{regex.join}$")
132
+ cr(regex)
130
133
  end
131
134
 
132
135
  # Returns regex for type with special types if needed
@@ -136,11 +139,11 @@ module Phonelib
136
139
  # * +data+ - country types data for single type
137
140
  # * +type+ - possible or valid regex type needed
138
141
  def type_regex(data, type)
139
- regex = [data[type]]
140
142
  if Phonelib.parse_special && data[Core::SHORT] && data[Core::SHORT][type]
141
- regex << data[Core::SHORT][type]
143
+ "#{data[type]}|#{data[Core::SHORT][type]}"
144
+ else
145
+ data[type]
142
146
  end
143
- regex.join('|')
144
147
  end
145
148
 
146
149
  # Check if phone match country data
@@ -150,9 +153,7 @@ module Phonelib
150
153
  # * +phone+ - phone number for parsing
151
154
  # * +data+ - country data
152
155
  def phone_match_data?(phone, data, possible = false)
153
- country_code = "#{data[Core::COUNTRY_CODE]}"
154
- inter_prefix = "(#{data[Core::INTERNATIONAL_PREFIX]})?"
155
- return unless phone.match cr("^0{2}?#{inter_prefix}#{country_code}")
156
+ return unless phone.match?(cr("^0{2}?(#{data[Core::INTERNATIONAL_PREFIX]})?#{data[Core::COUNTRY_CODE]}"))
156
157
 
157
158
  type = possible ? Core::POSSIBLE_PATTERN : Core::VALID_PATTERN
158
159
  phone.match full_regex_for_data(data, type, false)
@@ -161,10 +162,9 @@ module Phonelib
161
162
  # checks if types has both :mobile and :fixed_line and replaces it with
162
163
  # :fixed_or_mobile in case both present
163
164
  def sanitize_fixed_mobile(types)
164
- fixed_mobile = [Core::FIXED_LINE, Core::MOBILE]
165
- [:possible, :valid].each do |key|
166
- if (fixed_mobile - types[key]).empty?
167
- types[key] = types[key] - fixed_mobile + [Core::FIXED_OR_MOBILE]
165
+ Core::POSSIBLE_VALID_ARRAY.each do |key|
166
+ if (Core::FIXED_LINE_OR_MOBILE_ARRAY - types[key]).empty?
167
+ types[key] = types[key] - Core::FIXED_LINE_OR_MOBILE_ARRAY + Core::FIXED_OR_MOBILE_ARRAY
168
168
  end
169
169
  end
170
170
  types
@@ -178,7 +178,7 @@ module Phonelib
178
178
  def types_for_check(data)
179
179
  exclude_list = PhoneAnalyzer::NOT_FOR_CHECK
180
180
  exclude_list += Phonelib::Core::SHORT_CODES unless Phonelib.parse_special
181
- Core::TYPES_DESC.keys - exclude_list + fixed_and_mobile_keys(data)
181
+ Core::TYPES_DESC_KEYS - exclude_list + fixed_and_mobile_keys(data)
182
182
  end
183
183
 
184
184
  # Checks if fixed line pattern and mobile pattern are the same and returns
@@ -189,9 +189,9 @@ module Phonelib
189
189
  # * +data+ - country data
190
190
  def fixed_and_mobile_keys(data)
191
191
  if data[Core::FIXED_LINE] == data[Core::MOBILE]
192
- [Core::FIXED_OR_MOBILE]
192
+ Core::FIXED_OR_MOBILE_ARRAY
193
193
  else
194
- [Core::FIXED_LINE, Core::MOBILE]
194
+ Core::FIXED_LINE_OR_MOBILE_ARRAY
195
195
  end
196
196
  end
197
197
 
@@ -18,12 +18,19 @@ module Phonelib
18
18
  Phonelib::Core::EXT_GEO_NAME_KEY
19
19
  end
20
20
 
21
- # Returns timezone of parsed phone number or nil if number is invalid or
22
- # there is no timezone specified in db for this number
21
+ # Returns first timezone (in case several match) of parsed phone number or nil
22
+ # if number is invalid or there is no timezone specified in db for this number
23
23
  # @return [String|nil] timezone for parsed phone
24
24
  def timezone
25
- get_ext_name Phonelib::Core::EXT_TIMEZONES,
26
- Phonelib::Core::EXT_TIMEZONE_KEY
25
+ timezones.first
26
+ end
27
+
28
+ # Returns timezones of parsed phone number or nil if number is invalid or
29
+ # there is no timezone specified in db for this number
30
+ # @return [Array] timezones for parsed phone
31
+ def timezones
32
+ res = get_ext_name Phonelib::Core::EXT_TIMEZONES, Phonelib::Core::EXT_TIMEZONE_KEY
33
+ res.is_a?(Array) ? res : [res]
27
34
  end
28
35
 
29
36
  # Returns carrier of parsed phone number or nil if number is invalid or
@@ -53,9 +60,7 @@ module Phonelib
53
60
  def get_ext_name(names_key, id_key)
54
61
  return nil unless ext_data[id_key]
55
62
 
56
- res = Phonelib.phone_ext_data[names_key][ext_data[id_key]]
57
- return nil unless res
58
- res.size == 1 ? res.first : res
63
+ Phonelib.phone_ext_data[names_key][ext_data[id_key]]
59
64
  end
60
65
 
61
66
  # @private returns extended data ids for current number
@@ -54,7 +54,7 @@ module Phonelib
54
54
  def international(formatted = true, prefix = '+')
55
55
  prefix = formatted if formatted.is_a?(String)
56
56
  return nil if sanitized.empty?
57
- return "#{prefix}#{country_prefix_or_not}#{sanitized}" unless possible?
57
+ return "#{prefix}#{sanitized}" unless possible?
58
58
  return "#{prefix}#{data_country_code}#{@national_number}" unless formatted
59
59
 
60
60
  fmt = @data[country][:format]
@@ -137,12 +137,6 @@ module Phonelib
137
137
  true
138
138
  end
139
139
 
140
- # @private defines whether to put country prefix or not
141
- def country_prefix_or_not
142
- return '' unless data_country_code
143
- sanitized.start_with?(data_country_code) ? '' : data_country_code
144
- end
145
-
146
140
  # @private returns extension with separator defined
147
141
  def formatted_extension
148
142
  return '' if @extension.nil? || @extension.empty?
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Phonelib
4
4
  # @private
5
- VERSION = '0.10.3'
5
+ VERSION = '0.10.8'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phonelib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.3
4
+ version: 0.10.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vadim Senderovich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-16 00:00:00.000000000 Z
11
+ date: 2025-04-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  Google libphonenumber library was taken as a basis for
@@ -40,7 +40,7 @@ homepage: https://github.com/daddyz/phonelib
40
40
  licenses:
41
41
  - MIT
42
42
  metadata:
43
- changelog_uri: https://github.com/daddyz/phonelib/releases/tag/v0.10.3
43
+ changelog_uri: https://github.com/daddyz/phonelib/releases/tag/v0.10.8
44
44
  post_install_message:
45
45
  rdoc_options:
46
46
  - " --no-private - CHANGELOG.md --readme README.md"