Merge pull request #6997 from betagouv/fix-drom-phones-formatting
Correction de l'affichage des numéros de téléphone des DROM
This commit is contained in:
commit
92e79027c4
3 changed files with 69 additions and 4 deletions
|
@ -20,14 +20,43 @@
|
|||
# type_de_champ_id :integer
|
||||
#
|
||||
class Champs::PhoneChamp < Champs::TextChamp
|
||||
# We want to allow:
|
||||
# * international (e164) phone numbers
|
||||
# * “french format” (ten digits with a leading 0)
|
||||
# * DROM numbers
|
||||
#
|
||||
# However, we need to special-case some ten-digit numbers,
|
||||
# because the ARCEP assigns some blocks of "O6 XX XX XX XX" numbers to DROM operators.
|
||||
# Guadeloupe | GP | +590 | 0690XXXXXX, 0691XXXXXX
|
||||
# Guyane | GF | +594 | 0694XXXXXX
|
||||
# Martinique | MQ | +596 | 0696XXXXXX, 0697XXXXXX
|
||||
# Réunion | RE | +262 | 0692XXXXXX, 0693XXXXXX
|
||||
# Mayotte | YT | +262 | 0692XXXXXX, 0693XXXXXX
|
||||
# Nouvelle-Calédonie | NC | +687 |
|
||||
# Polynésie française | PF | +689 | 40XXXXXX, 45XXXXXX, 87XXXXXX, 88XXXXXX, 89XXXXXX
|
||||
#
|
||||
# Cf: Plan national de numérotation téléphonique,
|
||||
# https://www.arcep.fr/uploads/tx_gsavis/05-1085.pdf “Numéros mobiles à 10 chiffres”, page 6
|
||||
#
|
||||
# See issue #6996.
|
||||
DEFAULT_COUNTRY_CODES = [:FR, :GP, :GF, :MQ, :RE, :YT, :NC, :PF].freeze
|
||||
|
||||
validates :value,
|
||||
phone: {
|
||||
possible: true,
|
||||
allow_blank: true,
|
||||
message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages')
|
||||
}, unless: -> { Phonelib.valid_for_country?(value, :pf) }
|
||||
}, unless: -> { Phonelib.valid_for_countries?(value, DEFAULT_COUNTRY_CODES) }
|
||||
|
||||
def to_s
|
||||
value.present? ? Phonelib.parse(value).full_national : ''
|
||||
return '' if value.blank?
|
||||
|
||||
if Phonelib.valid_for_countries?(value, DEFAULT_COUNTRY_CODES)
|
||||
Phonelib.parse_for_countries(value, DEFAULT_COUNTRY_CODES).full_national
|
||||
else
|
||||
# When he phone number is possible for the default countries, but not strictly valid,
|
||||
# `full_national` could mess up the formatting. In this case just return the original.
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
14
lib/core_ext/phonelib.rb
Normal file
14
lib/core_ext/phonelib.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Class extensions to the Phonelib module, which allow parsing using several countries at once.
|
||||
module Phonelib
|
||||
# Variation of `.valid_for_country`, that can check several countries at once.
|
||||
def self.valid_for_countries?(value, countries)
|
||||
countries.any? { |country| valid_for_country?(value, country) }
|
||||
end
|
||||
|
||||
# Variation of `Phonelib.parse`, which parses the given string using the first country
|
||||
# for which the phone number is valid.
|
||||
def self.parse_for_countries(value, passed_countries = [])
|
||||
valid_country = passed_countries.find { |country| valid_for_country?(value, country) }
|
||||
parse(value, valid_country)
|
||||
end
|
||||
end
|
|
@ -22,6 +22,10 @@ describe Champs::PhoneChamp do
|
|||
expect(champ_with_value("+1(0) - 123456789")).to be_valid
|
||||
expect(champ_with_value("+49 2109 87654321")).to be_valid
|
||||
expect(champ_with_value("012345678")).to be_valid
|
||||
# DROM numbers should be valid
|
||||
expect(champ_with_value("06 96 04 78 07")).to be_valid
|
||||
expect(champ_with_value("05 94 22 31 31")).to be_valid
|
||||
expect(champ_with_value("+594 5 94 22 31 31")).to be_valid
|
||||
# polynesian numbers should not return errors in any way
|
||||
## landline numbers start with 40 or 45
|
||||
expect(champ_with_value("45187272")).to be_valid
|
||||
|
@ -36,9 +40,27 @@ describe Champs::PhoneChamp do
|
|||
expect(champ_with_value("88473500")).to be_valid
|
||||
expect(champ_with_value("89473500")).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
context 'for valid phone numbers' do
|
||||
it 'returns the national part of the number, formatted nicely' do
|
||||
expect(champ_with_value("0115789055").to_s).to eq("01 15 78 90 55")
|
||||
expect(champ_with_value("+33115789055").to_s).to eq("01 15 78 90 55")
|
||||
# DROM phone numbers are formatted differently – but still formatted
|
||||
expect(champ_with_value("0696047807").to_s).to eq("0696 04 78 07")
|
||||
expect(champ_with_value("45187272").to_s).to eq("45187272")
|
||||
end
|
||||
end
|
||||
|
||||
context 'for possible (but not valid) phone numbers' do
|
||||
it 'returns the original' do
|
||||
expect(champ_with_value("1234").to_s).to eq("1234")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def champ_with_value(number)
|
||||
phone_champ.tap { |c| c.value = number }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue