Module: PhoneNumber::Parser

Extended by:
Utils
Defined in:
lib/phoney/parser.rb

Class Method Summary collapse

Methods included from Utils

format, normalize

Class Method Details

.parse(phone_number, region_code = nil) ⇒ Object



9
10
11
# File 'lib/phoney/parser.rb', line 9

def parse(phone_number, region_code=nil)
  parse_to_parts(phone_number, region_code)[:formatted_number]
end

.parse_to_parts(phone_number, region_code = nil) ⇒ Object



13
14
15
16
17
18
19
20
21
22
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/phoney/parser.rb', line 13

def parse_to_parts(phone_number, region_code=nil)
  phone_number = normalize(phone_number.to_s)

  # we don't really need to do anything unless we get more input
  unless phone_number.length > 1
    return { :formatted_number => phone_number, :number => normalize(phone_number) }
  end

  region          = Region.find(region_code) || PhoneNumber.default_region
  country_code    = region.country_code.to_s
  prefix_code     = nil
  area_code       = nil

  dialout_prefix  = get_dialout_prefix(phone_number, region)
  national_prefix = get_national_prefix(phone_number, region)
  dialout_region  = get_dialout_region(phone_number, region)
  dialout_country = ''
  
  # No dialout prefix without a dialout region, and no dialout region without a prefix
  if((dialout_region && dialout_prefix.empty?) || (!dialout_region && !dialout_prefix.empty?))
    rule_sets = []
  else
    rule_sets = get_rule_sets_for_region(phone_number, dialout_region || region)
  end
  
  # build our total prefix
  if dialout_region
    prefix          = dialout_prefix.delete(' ') + dialout_region.country_code.to_s
    country_code    = dialout_region.country_code.to_s
    dialout_country = country_code
  else
    prefix  = national_prefix
    prefix += dialout_prefix.delete(' ') unless(dialout_prefix.empty?)
  end
  
  # strip the total prefix from the beginning of the number
  phone_number = phone_number[prefix.length..-1]
  number       = phone_number

  prefered_type = 0 # for sorting the priority
  
  # if we're dialing out or using the national prefix
  if(dialout_region || !national_prefix.empty?)
    # we need to sort the rules slightly different
    prefered_type = dialout_region.nil? ? 1 : 2
  end
  
  # sorting for rule priorities
  rule_sets.each do |rule_set|
    rule_set[:rules] = rule_set[:rules].sort_by do |rule|
      # [ prefered rule type ASC, total_digits ASC ]
      [ (rule[:type]==prefered_type) ? -1 : rule[:type], rule[:total_digits], rule[:index] ]
    end
  end
  
  # finally...find our matching rule
  matching_rule = find_matching_rule(phone_number, rule_sets)
  
  # now that know how to format the number, do the formatting work...
  if(matching_rule)
    if(matching_rule[:areacode_offset] > 0)
      prefix_code = phone_number[0, matching_rule[:areacode_offset]]
    end
    area_code     = phone_number[matching_rule[:areacode_offset], matching_rule[:areacode_length]]
    number        = phone_number[matching_rule[:areacode_offset]+matching_rule[:areacode_length]..-1]
    phone_number  = format(phone_number, matching_rule[:format].to_s)
  
    # replace 'n' with our national_prefix if it exists
    if(phone_number[/n/])
      phone_number.gsub!(/n{1}/, national_prefix)

      # reset the national_prefix so we don't add it twice
      national_prefix = ''
    end
  end
    
  # strip possible whitespace from the left
  phone_number.lstrip!
  
  if(matching_rule && phone_number[/c/])  
    # format the country code
    if(dialout_prefix == '+')
      phone_number.gsub!(/c{1}/, "+#{dialout_country}")
    else
      phone_number.gsub!(/c{1}/, dialout_country)
      phone_number = "#{dialout_prefix} #{phone_number}" unless dialout_prefix.empty?
    end
  else
    # default formatting
    if(dialout_prefix == '+')
      if(dialout_country.empty?)
        phone_number = "+#{phone_number}"
      else
        phone_number = "+#{dialout_country} #{phone_number}"
      end
    else
      phone_number = "#{dialout_country} #{phone_number}" unless dialout_country.empty?
      phone_number = "#{dialout_prefix} #{phone_number}" unless dialout_prefix.empty?
      phone_number = national_prefix + phone_number unless national_prefix.empty?
    end
  end
  
  # strip possible whitespace
  phone_number.rstrip!
  phone_number.lstrip!
  # remove possible non-numeric characters from the (invalid) number
  number.gsub!(/[^0-9]/,'') if number
  
  # Finally...we can output our parts as a hash
  { :formatted_number => phone_number,
    :prefix_code => prefix_code,
    :area_code => area_code,
    :country_code => country_code,
    :number => number }
end