From d3c34305d5044030a56818dbabe9b4b15ff89658 Mon Sep 17 00:00:00 2001 From: David Cantrell Date: Sat, 3 Dec 2011 01:11:33 +0000 Subject: [PATCH] Add StubCountry::* based on libphonenumber data --- CHANGELOG | 3 + MANIFEST | 216 ++++++++++++++++++++++++++++++++ build-data.nanp | 2 - build-data.sh | 8 ++ build-data.stubs | 107 ++++++++++++++++ lib/Number/Phone.pm | 39 +++--- lib/Number/Phone/StubCountry.pm | 40 +++++- t/40-no-stubs.t | 18 +++ t/902_bugfix-rt61177.t | 9 +- 9 files changed, 418 insertions(+), 24 deletions(-) create mode 100755 build-data.stubs create mode 100644 t/40-no-stubs.t diff --git a/CHANGELOG b/CHANGELOG index becca66..20bbbdb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ XXXX-XX-XX X.X Fix nasty bug in formatting unallocated UK numbers; Sint Maarten (SX) moved from +599 5 to +1 721; UK formatting improved for 3+7 and 2+8 formats; Isle of Man (IM) now sort-of treated as a country; + The minimal objects returned when there's no detailed + country-specific module available are far more + intelligent, thanks to libphonenumber's data; New UK allocations 2011-10-29 1.9 New UK allocations; diff --git a/MANIFEST b/MANIFEST index 4c39632..9325a2c 100644 --- a/MANIFEST +++ b/MANIFEST @@ -60,3 +60,219 @@ lib/Number/Phone/NANP/Data.pm lib/Number/Phone/NANP/SX.pm lib/Number/Phone/UK/IM.pm t/02_weird_little_islands.t +t/40-no-stubs.t +lib/Number/Phone/StubCountry/AC.pm +lib/Number/Phone/StubCountry/AD.pm +lib/Number/Phone/StubCountry/AE.pm +lib/Number/Phone/StubCountry/AF.pm +lib/Number/Phone/StubCountry/AL.pm +lib/Number/Phone/StubCountry/AM.pm +lib/Number/Phone/StubCountry/AN.pm +lib/Number/Phone/StubCountry/AO.pm +lib/Number/Phone/StubCountry/AR.pm +lib/Number/Phone/StubCountry/AT.pm +lib/Number/Phone/StubCountry/AU.pm +lib/Number/Phone/StubCountry/AW.pm +lib/Number/Phone/StubCountry/AX.pm +lib/Number/Phone/StubCountry/AZ.pm +lib/Number/Phone/StubCountry/BA.pm +lib/Number/Phone/StubCountry/BD.pm +lib/Number/Phone/StubCountry/BE.pm +lib/Number/Phone/StubCountry/BF.pm +lib/Number/Phone/StubCountry/BG.pm +lib/Number/Phone/StubCountry/BH.pm +lib/Number/Phone/StubCountry/BI.pm +lib/Number/Phone/StubCountry/BJ.pm +lib/Number/Phone/StubCountry/BL.pm +lib/Number/Phone/StubCountry/BN.pm +lib/Number/Phone/StubCountry/BO.pm +lib/Number/Phone/StubCountry/BR.pm +lib/Number/Phone/StubCountry/BT.pm +lib/Number/Phone/StubCountry/BW.pm +lib/Number/Phone/StubCountry/BY.pm +lib/Number/Phone/StubCountry/BZ.pm +lib/Number/Phone/StubCountry/CC.pm +lib/Number/Phone/StubCountry/CD.pm +lib/Number/Phone/StubCountry/CF.pm +lib/Number/Phone/StubCountry/CG.pm +lib/Number/Phone/StubCountry/CH.pm +lib/Number/Phone/StubCountry/CI.pm +lib/Number/Phone/StubCountry/CK.pm +lib/Number/Phone/StubCountry/CL.pm +lib/Number/Phone/StubCountry/CM.pm +lib/Number/Phone/StubCountry/CN.pm +lib/Number/Phone/StubCountry/CO.pm +lib/Number/Phone/StubCountry/CR.pm +lib/Number/Phone/StubCountry/CU.pm +lib/Number/Phone/StubCountry/CV.pm +lib/Number/Phone/StubCountry/CY.pm +lib/Number/Phone/StubCountry/CX.pm +lib/Number/Phone/StubCountry/CZ.pm +lib/Number/Phone/StubCountry/DE.pm +lib/Number/Phone/StubCountry/DJ.pm +lib/Number/Phone/StubCountry/DK.pm +lib/Number/Phone/StubCountry/DZ.pm +lib/Number/Phone/StubCountry/EC.pm +lib/Number/Phone/StubCountry/EE.pm +lib/Number/Phone/StubCountry/EG.pm +lib/Number/Phone/StubCountry/ER.pm +lib/Number/Phone/StubCountry/ES.pm +lib/Number/Phone/StubCountry/ET.pm +lib/Number/Phone/StubCountry/FI.pm +lib/Number/Phone/StubCountry/FJ.pm +lib/Number/Phone/StubCountry/FK.pm +lib/Number/Phone/StubCountry/FM.pm +lib/Number/Phone/StubCountry/FO.pm +lib/Number/Phone/StubCountry/FR.pm +lib/Number/Phone/StubCountry/GA.pm +lib/Number/Phone/StubCountry/MOCK.pm +lib/Number/Phone/StubCountry/GE.pm +lib/Number/Phone/StubCountry/GF.pm +lib/Number/Phone/StubCountry/GG.pm +lib/Number/Phone/StubCountry/GH.pm +lib/Number/Phone/StubCountry/GI.pm +lib/Number/Phone/StubCountry/GL.pm +lib/Number/Phone/StubCountry/GM.pm +lib/Number/Phone/StubCountry/GN.pm +lib/Number/Phone/StubCountry/GP.pm +lib/Number/Phone/StubCountry/GQ.pm +lib/Number/Phone/StubCountry/GR.pm +lib/Number/Phone/StubCountry/GT.pm +lib/Number/Phone/StubCountry/GW.pm +lib/Number/Phone/StubCountry/GY.pm +lib/Number/Phone/StubCountry/HK.pm +lib/Number/Phone/StubCountry/HN.pm +lib/Number/Phone/StubCountry/HR.pm +lib/Number/Phone/StubCountry/HT.pm +lib/Number/Phone/StubCountry/HU.pm +lib/Number/Phone/StubCountry/ID.pm +lib/Number/Phone/StubCountry/IE.pm +lib/Number/Phone/StubCountry/IL.pm +lib/Number/Phone/StubCountry/IM.pm +lib/Number/Phone/StubCountry/IN.pm +lib/Number/Phone/StubCountry/IO.pm +lib/Number/Phone/StubCountry/IQ.pm +lib/Number/Phone/StubCountry/IR.pm +lib/Number/Phone/StubCountry/IS.pm +lib/Number/Phone/StubCountry/IT.pm +lib/Number/Phone/StubCountry/JE.pm +lib/Number/Phone/StubCountry/JO.pm +lib/Number/Phone/StubCountry/JP.pm +lib/Number/Phone/StubCountry/KE.pm +lib/Number/Phone/StubCountry/KG.pm +lib/Number/Phone/StubCountry/KH.pm +lib/Number/Phone/StubCountry/KI.pm +lib/Number/Phone/StubCountry/KM.pm +lib/Number/Phone/StubCountry/KP.pm +lib/Number/Phone/StubCountry/KR.pm +lib/Number/Phone/StubCountry/KW.pm +lib/Number/Phone/StubCountry/KZ.pm +lib/Number/Phone/StubCountry/LA.pm +lib/Number/Phone/StubCountry/LB.pm +lib/Number/Phone/StubCountry/LI.pm +lib/Number/Phone/StubCountry/LK.pm +lib/Number/Phone/StubCountry/LR.pm +lib/Number/Phone/StubCountry/LS.pm +lib/Number/Phone/StubCountry/LT.pm +lib/Number/Phone/StubCountry/LU.pm +lib/Number/Phone/StubCountry/LV.pm +lib/Number/Phone/StubCountry/LY.pm +lib/Number/Phone/StubCountry/MA.pm +lib/Number/Phone/StubCountry/MC.pm +lib/Number/Phone/StubCountry/MD.pm +lib/Number/Phone/StubCountry/ME.pm +lib/Number/Phone/StubCountry/MG.pm +lib/Number/Phone/StubCountry/MF.pm +lib/Number/Phone/StubCountry/MH.pm +lib/Number/Phone/StubCountry/MK.pm +lib/Number/Phone/StubCountry/ML.pm +lib/Number/Phone/StubCountry/MM.pm +lib/Number/Phone/StubCountry/MN.pm +lib/Number/Phone/StubCountry/MO.pm +lib/Number/Phone/StubCountry/MQ.pm +lib/Number/Phone/StubCountry/MR.pm +lib/Number/Phone/StubCountry/MT.pm +lib/Number/Phone/StubCountry/MU.pm +lib/Number/Phone/StubCountry/MV.pm +lib/Number/Phone/StubCountry/MW.pm +lib/Number/Phone/StubCountry/MX.pm +lib/Number/Phone/StubCountry/MY.pm +lib/Number/Phone/StubCountry/MZ.pm +lib/Number/Phone/StubCountry/NA.pm +lib/Number/Phone/StubCountry/NC.pm +lib/Number/Phone/StubCountry/NE.pm +lib/Number/Phone/StubCountry/NF.pm +lib/Number/Phone/StubCountry/NG.pm +lib/Number/Phone/StubCountry/NI.pm +lib/Number/Phone/StubCountry/NL.pm +lib/Number/Phone/StubCountry/NO.pm +lib/Number/Phone/StubCountry/NP.pm +lib/Number/Phone/StubCountry/NR.pm +lib/Number/Phone/StubCountry/NU.pm +lib/Number/Phone/StubCountry/NZ.pm +lib/Number/Phone/StubCountry/OM.pm +lib/Number/Phone/StubCountry/PA.pm +lib/Number/Phone/StubCountry/PE.pm +lib/Number/Phone/StubCountry/PF.pm +lib/Number/Phone/StubCountry/PG.pm +lib/Number/Phone/StubCountry/PH.pm +lib/Number/Phone/StubCountry/PK.pm +lib/Number/Phone/StubCountry/PL.pm +lib/Number/Phone/StubCountry/PM.pm +lib/Number/Phone/StubCountry/PS.pm +lib/Number/Phone/StubCountry/PT.pm +lib/Number/Phone/StubCountry/PW.pm +lib/Number/Phone/StubCountry/PY.pm +lib/Number/Phone/StubCountry/QA.pm +lib/Number/Phone/StubCountry/RE.pm +lib/Number/Phone/StubCountry/RO.pm +lib/Number/Phone/StubCountry/RS.pm +lib/Number/Phone/StubCountry/RU.pm +lib/Number/Phone/StubCountry/RW.pm +lib/Number/Phone/StubCountry/SA.pm +lib/Number/Phone/StubCountry/SB.pm +lib/Number/Phone/StubCountry/SC.pm +lib/Number/Phone/StubCountry/SD.pm +lib/Number/Phone/StubCountry/SE.pm +lib/Number/Phone/StubCountry/SG.pm +lib/Number/Phone/StubCountry/SH.pm +lib/Number/Phone/StubCountry/SI.pm +lib/Number/Phone/StubCountry/SJ.pm +lib/Number/Phone/StubCountry/SK.pm +lib/Number/Phone/StubCountry/SL.pm +lib/Number/Phone/StubCountry/SM.pm +lib/Number/Phone/StubCountry/SN.pm +lib/Number/Phone/StubCountry/SO.pm +lib/Number/Phone/StubCountry/SR.pm +lib/Number/Phone/StubCountry/ST.pm +lib/Number/Phone/StubCountry/SV.pm +lib/Number/Phone/StubCountry/SY.pm +lib/Number/Phone/StubCountry/SZ.pm +lib/Number/Phone/StubCountry/TD.pm +lib/Number/Phone/StubCountry/TG.pm +lib/Number/Phone/StubCountry/TH.pm +lib/Number/Phone/StubCountry/TJ.pm +lib/Number/Phone/StubCountry/TK.pm +lib/Number/Phone/StubCountry/TL.pm +lib/Number/Phone/StubCountry/TM.pm +lib/Number/Phone/StubCountry/TN.pm +lib/Number/Phone/StubCountry/TO.pm +lib/Number/Phone/StubCountry/TR.pm +lib/Number/Phone/StubCountry/TV.pm +lib/Number/Phone/StubCountry/TW.pm +lib/Number/Phone/StubCountry/TZ.pm +lib/Number/Phone/StubCountry/UA.pm +lib/Number/Phone/StubCountry/UG.pm +lib/Number/Phone/StubCountry/UY.pm +lib/Number/Phone/StubCountry/UZ.pm +lib/Number/Phone/StubCountry/VA.pm +lib/Number/Phone/StubCountry/VE.pm +lib/Number/Phone/StubCountry/VN.pm +lib/Number/Phone/StubCountry/VU.pm +lib/Number/Phone/StubCountry/WF.pm +lib/Number/Phone/StubCountry/WS.pm +lib/Number/Phone/StubCountry/YE.pm +lib/Number/Phone/StubCountry/YT.pm +lib/Number/Phone/StubCountry/ZA.pm +lib/Number/Phone/StubCountry/ZM.pm +lib/Number/Phone/StubCountry/ZW.pm diff --git a/build-data.nanp b/build-data.nanp index 973ca71..259a150 100755 --- a/build-data.nanp +++ b/build-data.nanp @@ -7,8 +7,6 @@ use strict; use warnings; -use lib 'lib'; - open(MODULE, '>lib/Number/Phone/NANP/Data.pm') || die("Can't write lib/Number/Phone/NANP/Data.pm\n"); print MODULE "# automatically generated file, don't edit\n\n"; diff --git a/build-data.sh b/build-data.sh index 3c78767..baa550a 100755 --- a/build-data.sh +++ b/build-data.sh @@ -28,3 +28,11 @@ if test ! -e lib/Number/Phone/NANP/Data.pm -o libphonenumber/resources/geocoding else echo lib/Number/Phone/NANP/Data.pm is up-to-date fi + +# lib/Number/Phone/StubCountry/MOCK.pm doesn't exist, or if libphonenumber/resources/PhoneNumberMetaData.xml is newer ... +if test ! -e lib/Number/Phone/StubCountry/MOCK.pm -o libphonenumber/resources/PhoneNumberMetaData.xml -nt lib/Number/Phone/StubCountry/MOCK.pm; then + echo rebuilding lib/Number/Phone/StubCountry/\*.pm + perl build-data.stubs +else + echo lib/Number/Phone/StubCountry/\*.pm are up-to-date +fi diff --git a/build-data.stubs b/build-data.stubs new file mode 100755 index 0000000..9e3ef7b --- /dev/null +++ b/build-data.stubs @@ -0,0 +1,107 @@ +#!/usr/local/bin/perl + +# THIS SCRIPT IS NOT INTENDED FOR END USERS OR FOR PEOPLE INSTALLING +# THE MODULES, BUT FOR THE AUTHOR'S USE WHEN UPDATING THE DATA FROM OFCOM'S +# PUBLISHED DATA. + +use strict; +use warnings; +use Data::Dumper; local $Data::Dumper::Indent = 0; + +use XML::XPath; +my $xml = XML::XPath->new(filename => 'libphonenumber/resources/PhoneNumberMetaData.xml'); +my @territories = $xml->find('/phoneNumberMetadata/territories/territory')->get_nodelist(); + +open(my $manifest_fh, 'MANIFEST') || die("Can't read MANIFEST\n"); +my @manifest_files = grep { /./ } <$manifest_fh>; +close($manifest_fh); +open($manifest_fh, '>', 'MANIFEST') || die("Can't write MANIFEST\n"); +print $manifest_fh "$_" foreach( grep { $_ !~ m{^lib/Number/Phone/StubCountry/} } @manifest_files); + +mkdir('lib/Number/Phone/StubCountry'); + +foreach my $territory (@territories) { + my $IDD_country_code = ''.$territory->find('@countryCode'); + next if($IDD_country_code eq '1'); # no point stubbing NANP! + + my $ISO_country_code = ''.$territory->find('@id'); + # no need to create a stub for the UK, so use this for testing instead + $ISO_country_code = $ISO_country_code eq 'GB' ? 'MOCK' : $ISO_country_code; + + open(my $module_fh, '>', "lib/Number/Phone/StubCountry/$ISO_country_code.pm") + || die("Can't write lib/Number/Phone/StubCountry/$ISO_country_code.pm: $!\n"); + print $manifest_fh "lib/Number/Phone/StubCountry/$ISO_country_code.pm\n"; + print $module_fh preamble($ISO_country_code); + + my @number_formats = $territory->find('availableFormats/numberFormat')->get_nodelist(); + + my @formatters = (); + foreach my $number_format (@number_formats) { + my $number_format_pattern = ''.$number_format->find('@pattern'); + my @leading_digit_patterns = $number_format->find('leadingDigits')->get_nodelist(); + my $formatter = ''.$number_format->find('format'); + + foreach (map { (my $f = $_->string_value()) =~ s/\s//g; $f; } @leading_digit_patterns) { + push @formatters, { + leading_digits => $_, + pattern => $number_format_pattern + }; + } + } + + print $module_fh 'my '.Data::Dumper->new([\@formatters], [qw(formatters)])->Dump()."\n"; + print $module_fh 'my '.Data::Dumper->new([{ + special_rate => join('|', map { + (my $foo = '('.$territory->find("$_/nationalNumberPattern")->string_value().')') + =~ s/\s//g; + $foo; + } qw(sharedCost premiumRate)), + map { + (my $xpath = $_) =~ s/_(\w)/uc($1)/eg; + (my $pattern = $territory->find("$xpath/nationalNumberPattern")->string_value()) + =~ s/\s//g; + ($_ => $pattern); + } qw(fixed_line mobile pager toll_free personal_number) + }], [qw(validators)])->Dump(); + print $module_fh < \$number, formatters => \$formatters, validators => \$validators }, \$class); + return \$self->is_valid() ? \$self : undef; +} + +1; +EOCODE + ; +} + +sub preamble { + my $iso_code = shift; + "# automatically generated file, don't edit\n\n". + q{ + +# Copyright 2011 David Cantrell, derived from data from libphonenumber +# http://code.google.com/p/libphonenumber/ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +package Number::Phone::StubCountry::}.$iso_code.q{; +use base qw(Number::Phone::StubCountry); + +use strict; +use warnings; +}. + "our \$VERSION = 1.".join("", (gmtime())[5] + 1900, sprintf('%02d', (gmtime())[4] + 1), map { sprintf('%02d', $_) } (gmtime())[3, 2, 1, 0]).";\n\n"; +} diff --git a/lib/Number/Phone.pm b/lib/Number/Phone.pm index c160ae9..70b9685 100644 --- a/lib/Number/Phone.pm +++ b/lib/Number/Phone.pm @@ -9,6 +9,16 @@ use Number::Phone::StubCountry; our $VERSION = 1.9; +my $NOSTUBS = 0; +sub import { + my $class = shift; + my @params = @_; + if(grep { /^nostubs$/ } @params) { + $NOSTUBS++ + } +} + + my @is_methods = qw( is_valid is_allocated is_in_use is_geographic is_fixed_line is_mobile is_pager @@ -103,10 +113,14 @@ If you pass in a bogus country code not recognised by Number::Phone::Country, the constructor will return undef. If you pass in a country code for which -no supporting module is available, the constructor will return a -minimal object that knows its country code and how to format a phone -number, but nothing else. Note that this is an incompatible change: -previously it would return undef. +no supporting module is available, the constructor will try to use a 'stub' +class under Number::Phone::StubCountry::* that uses data automatically +extracted from Google's libphonenumber project. libphonenumber doesn't +have enough data to support all the features of Number::Phone, and this +is an experimental feature. If you want to disable this, then pass 'nostubs' +when you use the module: + + use Number::Phone qw(nostubs); =cut @@ -141,17 +155,14 @@ sub new { } sub _make_stub_object { - my $class = shift; + shift; my $number = shift; - my $self = { - country => 'STUBFORCOUNTRYWITHNOMODULE', - country_idd_code => ''.Number::Phone::Country::country_code(Number::Phone::Country::phone2country($number)), - country_code => ''.Number::Phone::Country::phone2country($number), - number => $number - }; - # use Data::Dumper; local $Data::Dumper::Indent = 1; - # print Dumper($self); - bless($self, 'Number::Phone::StubCountry'); + my $country_code = ''.Number::Phone::Country::phone2country($number); + die("no module available for +$country_code, and nostubs turned on\n") if($NOSTUBS); + my $class = "Number::Phone::StubCountry::$country_code"; + eval "use $class"; + die("Can't find $class: $@\n") if($@); + $class->new($number); } =head1 METHODS diff --git a/lib/Number/Phone/StubCountry.pm b/lib/Number/Phone/StubCountry.pm index 383fa93..4b9525b 100644 --- a/lib/Number/Phone/StubCountry.pm +++ b/lib/Number/Phone/StubCountry.pm @@ -2,15 +2,47 @@ package Number::Phone::StubCountry; use strict; use warnings; +use Number::Phone::Country qw(noexport uk); + use base qw(Number::Phone); -sub country_code { return shift()->{country_idd_code} } +sub country_code { return Number::Phone::Country::country_code(shift()->country()); } +sub country { (my $self = ref(shift)) =~ /::(\w\w(\w\w)?)$/; $1; } # extra \w\w is for MOCK during testing + +sub is_valid { + my $self = shift; + foreach (map { "is_$_" } qw(special_rate fixed_line mobile pager tollfree personal)) { + return 1 if($self->$_()); + } + return 0; +} + +sub is_geographic { shift()->is_fixed_line() } +sub is_fixed_line { shift()->_validator('fixed_line'); } +sub is_mobile { shift()->_validator('mobile'); } +sub is_pager { shift()->_validator('pager'); } +sub is_personal { shift()->_validator('personal_number'); } +sub is_special_rate { shift()->_validator('special_rate'); } +sub is_tollfree { shift()->_validator('toll_free'); } + +sub _validator { + my($self, $validator) = @_; + $validator = $self->{validators}->{$validator}; + return undef unless($validator); + return $self->{number} =~ /^$validator$/ ? 1 : 0; +} + sub format { my $self = shift; my $number = $self->{number}; - my $cc = $self->country_code(); - $number =~ s/^(\+$cc)/$1 /; - return $number + foreach my $formatter (@{$self->{formatters}}) { + my($leading_digits, $pattern) = map { $formatter->{$_} } qw(leading_digits pattern); + if($number =~ /^$leading_digits/ && $number =~ /^$pattern$/) { + my @bits = $number =~ /^$pattern$/; + return join(' ', '+'.$self->country_code(), @bits); + } + } + return '+'.$self->country_code().' '.$number; } 1; diff --git a/t/40-no-stubs.t b/t/40-no-stubs.t new file mode 100644 index 0000000..82ae62d --- /dev/null +++ b/t/40-no-stubs.t @@ -0,0 +1,18 @@ +#!/usr/bin/perl -w + +use strict; + +use Number::Phone qw(nostubs); + +use Test::More tests => 2; + +use Number::Phone::Country; + +ok(Number::Phone->new("+442087712924")->country_code() == 44, "known countries return objects"); + +# let's break the UK +$Number::Phone::Country::idd_codes{'44'} = 'MOCK'; +$Number::Phone::Country::prefix_codes{'MOCK'} = ['44', '00', undef]; + +eval { Number::Phone->new('+442087712924') }; +ok($@, "nostubs works"); diff --git a/t/902_bugfix-rt61177.t b/t/902_bugfix-rt61177.t index 3e0048d..cbf9a29 100644 --- a/t/902_bugfix-rt61177.t +++ b/t/902_bugfix-rt61177.t @@ -4,21 +4,22 @@ use strict; use Number::Phone; -use Test::More tests => 9; +use Test::More tests => 11; use Number::Phone::Country; ok(Number::Phone->new("442087712924")->country_code() == 44, "known countries return objects"); ok(Number::Phone->new("+442087712924")->country_code() == 44, "known countries with a + return objects"); -ok(Number::Phone->new("+442087712924")->format() eq '+44 20 8771 2924' , "format() works (sanity check cos it changes later)"); +is(Number::Phone->new("+447979866975")->format(), '+44 7979866975' , "format() works (sanity check cos it changes later)"); # let's break the UK $Number::Phone::Country::idd_codes{'44'} = 'MOCK'; $Number::Phone::Country::prefix_codes{'MOCK'} = ['44', '00', undef]; foreach my $prefix ('', '+') { - my $object = Number::Phone->new($prefix."442087712924"); + my $object = Number::Phone->new($prefix."447979866975"); isa_ok($object, 'Number::Phone::StubCountry', "unknown countries return minimal objects".($prefix? " with a +" : "")); + isa_ok($object, 'Number::Phone::StubCountry::MOCK', "class hierarchy is correct"); is($object->country_code(), '44', "->country_code works"); - is($object->format(), '+44 2087712924', "->format works"); + is($object->format(), '+44 797 986 6975', "->format works"); }