Commit b7716917 authored by gregor herrmann's avatar gregor herrmann

New upstream version 3.4003

parents 0036ec88 5281a09b
2018-01-08 3.4003 UK "protected" numbers should have false is_allocated();
Bugfix for countries that don't have area names (see
https://github.com/DrHyde/perl-modules-Number-Phone/issues/64);
Match libphonenumber's behaviour when countries have identical
validators for fixed_line and mobile (see
https://github.com/DrHyde/perl-modules-Number-Phone/issues/84);
Accept numbers in some more unusual national dialling formats (see
https://github.com/DrHyde/perl-modules-Number-Phone/issues/77);
Recognise some more special rate numbers in Barbados and Bahamas (see
https://github.com/DrHyde/perl-modules-Number-Phone/pull/86);
Add format_for_country method;
Data updates
2017-09-05 3.4002 Add new US and CA area codes;
UK data is now in a normal data file instead of a humungous binary
module;
......
......@@ -75,6 +75,8 @@ t/country-test-at.t
t/number-phone-country-multiple.t
t/country-test-br.t
t/formatters.t
lib/Number/Phone/Formatter.pm
lib/Number/Phone/Formatter/National.pm
lib/Number/Phone/Formatter/Raw.pm
lib/Number/Phone/Formatters.pod
t/number-phone-country-warnings.t
......@@ -82,6 +84,7 @@ t/pod-coverage.t
t/example-phone-numbers.t
share/Number-Phone-UK-Data.db
t/uk_slurp.t
lib/Number/Phone/Formatter/NationallyPreferredIntl.pm
lib/Number/Phone/StubCountry/AC.pm
lib/Number/Phone/StubCountry/AD.pm
lib/Number/Phone/StubCountry/AE.pm
......
......@@ -4,10 +4,10 @@
"unknown"
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010",
"generated_by" : "ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150001",
"license" : [
"unknown",
"unknown"
"open_source"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
......@@ -60,6 +60,5 @@
"url" : "https://github.com/DrHyde/perl-modules-Number-Phone"
}
},
"version" : "3.4002",
"x_serialization_backend" : "JSON::PP version 2.27400_02"
"version" : "3.4003"
}
......@@ -13,7 +13,7 @@ configure_requires:
ExtUtils::Manifest: '0'
File::ShareDir::Install: '0.11'
dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010'
generated_by: 'ExtUtils::MakeMaker version 7.3, CPAN::Meta::Converter version 2.150001'
license: unknown
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
......@@ -36,5 +36,4 @@ requires:
resources:
bugtracker: https://github.com/DrHyde/perl-modules-Number-Phone/issues
repository: https://github.com/DrHyde/perl-modules-Number-Phone
version: '3.4002'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
version: '3.4003'
......@@ -10,7 +10,7 @@ install_share 'share';
WriteMakefile(
NAME => 'Number::Phone',
META_MERGE => {
license => 'other',
license => 'open_source',
resources => {
repository => 'https://github.com/DrHyde/perl-modules-Number-Phone',
bugtracker => 'https://github.com/DrHyde/perl-modules-Number-Phone/issues'
......
......@@ -8,7 +8,7 @@ use Number::Phone::Country qw(noexport);
use Number::Phone::StubCountry;
# MUST be in format N.NNNN, see https://github.com/DrHyde/perl-modules-Number-Phone/issues/58
our $VERSION = '3.4002';
our $VERSION = '3.4003';
my $NOSTUBS = 0;
sub import {
......@@ -92,8 +92,17 @@ sub format_using {
eval "use Number::Phone::Formatter::$format";
die("Couldn't load format '$format': $@\n") if($@);
return "Number::Phone::Formatter::$format"->format($self->format());
return "Number::Phone::Formatter::$format"->format($self->format(), $self);
}
sub format_for_country {
my $self = shift;
my $country_code = shift || '';
$country_code = Number::Phone::Country::country_code($country_code)
if $country_code && $country_code =~ /[a-z]/i;
$country_code =~ s/^\+//;
return $self->format_using('National') if $country_code eq $self->country_code();
return $self->format_using('NationallyPreferredIntl');
}
1;
......@@ -451,6 +460,14 @@ which will return:
It is a fatal error to specify a non-existent formatter.
=item format_for_country
Given a country code (either two-letter ISO or numeric prefix), return the
number formatted either nationally-formatted, if the number is in the same
country, or as a nationally-preferred international number if not. Internally
this uses the National and NationallyPreferredIntl formatters. Beware of the
potential performance hit!
=item country
The two letter ISO country code for the country in which the call will
......
package Number::Phone::Formatter;
use strict;
use warnings;
our $VERSION = '1.0';
use Number::Phone::Lib;
sub _regex_variable {
my ($var, $qr, $subs) = @_;
$subs =~ s/"/\\"/;
$subs = "\"$subs\"";
$var =~ s/$qr/$subs/xee;
return $var;
}
sub _maybe_add_country {
my ($object, $number, $national) = @_;
$number = '+' . $object->country_code() . ' ' . $number unless $national;
return $number;
}
# this is used by N::P::Formatter::National(lyPreferredIntl), it wants
# something that looks very much like a N::P::StubCountry::XX as those
# will contain libphonenumber's formatting data. If we're instead passed
# a full-fat object, it will first create the equivalent stub.
sub _format {
my ($class, $object, $national) = @_;
if(!$object->isa('Number::Phone::StubCountry')) {
$object = Number::Phone::Lib->new($object->format())
}
my $number = $object->{number};
foreach my $formatter (@{$object->{formatters}}) {
my ($leading_digits, $pattern) = map { $formatter->{$_} } qw(leading_digits pattern);
if ((!$leading_digits || $number =~ /^($leading_digits)/x) && $number =~ /^$pattern$/x) {
my $format;
if ($national && $formatter->{national_rule}) {
$format = _regex_variable($formatter->{format}, qr/(\$\d)/, $formatter->{national_rule});
} else {
$format = $formatter->{intl_format} || $formatter->{format};
}
$number = _regex_variable($number, qr/^$pattern$/, $format);
return _maybe_add_country($object, $number, $national);
}
}
return _maybe_add_country($object, $number, $national);
}
1;
=head1 NAME
Number::Phone::Formatter - base class for other formatters
=head1 DESCRIPTION
A base class containing utility functions used by the formatters.
=head1 AUTHOR, COPYRIGHT and LICENCE
Copyright 2018 Matthew Somerville E<lt>F<matthew-github@dracos.co.uk>E<gt>
This software is free-as-in-speech software, and may be used,
distributed, and modified under the terms of either the GNU
General Public Licence version 2 or the Artistic Licence. It's
up to you which one you use. The full text of the licences can
be found in the files GPL2.txt and ARTISTIC.txt, respectively.
=cut
package Number::Phone::Formatter::National;
use strict;
use warnings;
use parent 'Number::Phone::Formatter';
use Scalar::Util qw(reftype);
our $VERSION = '1.0';
sub format {
my ($class, $number, $object) = @_;
$class->_format($object, 1);
}
1;
=head1 NAME
Number::Phone::Formatter::National - formatter for nationally-formatted phone number
=head1 DESCRIPTION
A formatter to output the number in its national format.
=head1 METHOD
=head2 format
This is the only method. It takes an E.123 international format string and a Number::Phone object,
and outputs the nationally-formatted number.
+1 212 334 0611 -> 212-334-0611
Note that this uses data derived from libphonenumber, and if your object is
not derived from that it will first create a temporary object. This may
involve a small unexpected performance hit.
=head1 AUTHOR, COPYRIGHT and LICENCE
Copyright 2018 Matthew Somerville E<lt>F<matthew-github@dracos.co.uk>E<gt>
This software is free-as-in-speech software, and may be used,
distributed, and modified under the terms of either the GNU
General Public Licence version 2 or the Artistic Licence. It's
up to you which one you use. The full text of the licences can
be found in the files GPL2.txt and ARTISTIC.txt, respectively.
=cut
package Number::Phone::Formatter::NationallyPreferredIntl;
use strict;
use warnings;
use parent 'Number::Phone::Formatter';
use Scalar::Util qw(reftype);
our $VERSION = '1.0';
sub format {
my ($class, $number, $object) = @_;
$class->_format($object, 0);
}
1;
=head1 NAME
Number::Phone::Formatter::NationallyPreferredIntl - nationally-preferred format for international phone number
=head1 DESCRIPTION
A formatter to output the international number in its nationally preferred format.
=head1 METHOD
=head2 format
This is the only method. It takes an E.123 international format string and a Number::Phone object,
and outputs the nationally-preferred international representation of the phone number.
+1 212 334 0611 -> +1 212-334-0611
Note that this uses data derived from libphonenumber, and if your object is
not derived from that it will first create a temporary object. This may
involve a small unexpected performance hit.
=head1 AUTHOR, COPYRIGHT and LICENCE
Copyright 2018 Matthew Somerville E<lt>F<matthew-github@dracos.co.uk>E<gt>
This software is free-as-in-speech software, and may be used,
distributed, and modified under the terms of either the GNU
General Public Licence version 2 or the Artistic Licence. It's
up to you which one you use. The full text of the licences can
be found in the files GPL2.txt and ARTISTIC.txt, respectively.
=cut
......@@ -23,8 +23,10 @@ guaranteed to not exist so I could test that it failed correctly.
There is one compulsory method, C<format> that you must write. It will
be called as a class method, with a number in E.123 international format as its
only argument, looking something like '+CC NNN NNN NNN'. The gory details
are at L<http://www.itu.int/rec/T-REC-E.123/en> but in summary, you'll get:
first argument, looking something like '+CC NNN NNN NNN', and a Number::Phone
object as its second argument. The gory details of what E.123 looks like
are at L<http://www.itu.int/rec/T-REC-E.123/en> but in summary, you'll get
a string consisting of:
=over
......@@ -38,9 +40,13 @@ are at L<http://www.itu.int/rec/T-REC-E.123/en> but in summary, you'll get:
=back
You should return a string.
=head1 EXAMPLE
See L<Number::Phone::Formatter::Raw> for an example.
See L<Number::Phone::Formatter::Raw> for an example that uses the string
argument, and L<Number::Phone::Formatter::NationallyPreferredIntl> for one
that uses the object.
=head1 COPYRIGHT and LICENCE
......
......@@ -9,7 +9,7 @@ use Number::Phone::NANP::Data;
use Number::Phone::Country qw(noexport);
our $VERSION = 1.5;
our $VERSION = '1.6000';
my $cache = {};
......@@ -219,7 +219,8 @@ sub is_specialrate {
^(\+1)?
(
900 | # NANP-global
246 ( 292 | 41[7-9] | 43[01] ) # BB-specific, apparently
242225[0-46-9] | # BS-specific
246 ( 292 | 367 | 41[7-9] | 43[01] | 444 | 467 | 736 ) # BB-specific, apparently
)
/x) { return 1; }
else { return 0; }
......
......@@ -21,7 +21,7 @@
use strict;
use warnings;
use vars qw(%areanames %fixed_line_regexes %mobile_regexes);
our $VERSION = 1.20170908113144;
our $VERSION = 1.20180203200229;
......@@ -2253,6 +2253,7 @@ our $VERSION = 1.20170908113144;
'1219989' => "Hammond\,\ IN",
'1219996' => "Hebron\,\ IN",
'1220' => "Ohio",
'1223' => "Pennsylvania",
'1224' => "Illinois",
'1224610' => "North\ Chicago\,\ IL",
'1224653' => "Schaumburg\,\ IL",
......@@ -2748,7 +2749,7 @@ our $VERSION = 1.20170908113144;
'1242326' => "New\ Providence",
'1242327' => "New\ Providence",
'1242328' => "New\ Providence",
'1242329' => "North\ Andros",
'1242329' => "Andros",
'1242331' => "Rum\ Cay\ \&\ San\ Sal",
'1242332' => "Eleuthera",
'1242333' => "Eleuthera",
......@@ -2761,7 +2762,7 @@ our $VERSION = 1.20170908113144;
'1242340' => "New\ Providence",
'1242341' => "New\ Providence",
'1242342' => "Cat\ Island",
'1242344' => "Acklins",
'1242344' => "Ragged\ Island\/Crooked\ Island\/Acklins",
'1242345' => "Exuma",
'1242346' => "Grand\ Bahama",
'1242347' => "Bimini\ and\ Cat\ Cay",
......@@ -2799,14 +2800,15 @@ our $VERSION = 1.20170908113144;
'1242396' => "New\ Providence",
'1242397' => "New\ Providence",
'1242461' => "New\ Providence",
'1242502' => "New\ Providence",
'1242601' => "New\ Providence",
'1242602' => "Grand\ Bahama",
'1242676' => "New\ Providence",
'1242677' => "New\ Providence",
'1242687' => "Grand\ Bahama",
'1242688' => "Grand\ Bahama",
'1242698' => "Abaco",
'1242699' => "Abaco",
'1242698' => "New\ Providence",
'1242699' => "Abaco\/Eleuthera",
'1242702' => "New\ Providence",
'1248' => "Michigan",
'1248208' => "Southfield\,\ MI",
......@@ -24782,6 +24784,7 @@ our $VERSION = 1.20170908113144;
'1724966' => "Carmichaels\,\ PA",
'1724981' => "Hermitage\,\ PA",
'1725' => "Nevada",
'1726' => "San\ Antonio\,\ TX",
'1727' => "Florida",
'1727298' => "Clearwater\,\ FL",
'1727321' => "St\.\ Petersburg\,\ FL",
......@@ -36282,11 +36285,11 @@ $mobile_regexes{AI} = '264(?:235|476|5(?:3[6-9]|8[1-4])|7(?:29|72))\d{4}';
$fixed_line_regexes{AS} = '6846(?:22|33|44|55|77|88|9[19])\d{4}';
$mobile_regexes{AS} = '684(?:2(?:5[2468]|72)|7(?:3[13]|70))\d{4}';
$fixed_line_regexes{BB} = '246(?:2(?:2[78]|7[0-4])|4(?:1[024-6]|2\d|3[2-9])|5(?:20|[34]\d|54|7[1-3])|6(?:2\d|38)|7(?:37|57)|9(?:1[89]|63))\d{4}';
$mobile_regexes{BB} = '246(?:2(?:[356]\d|4[0-57-9]|8[0-79])|45\d|8(?:[2-5]\d|83))\d{4}';
$mobile_regexes{BB} = '246(?:2(?:[356]\d|4[0-57-9]|8[0-79])|45\d|69[5-7]|8(?:[2-5]\d|83))\d{4}';
$fixed_line_regexes{BM} = '441(?:2(?:02|23|61|[3479]\d)|[46]\d{2}|5(?:4\d|60|89)|824)\d{4}';
$mobile_regexes{BM} = '441(?:[37]\d|5[0-39])\d{5}';
$fixed_line_regexes{BS} = '242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[3467]|8[0-4]|9[2-467])|461|502|6(?:0[1-3]|12|7[67]|8[78]|9[89])|7(?:02|88))\d{4}';
$mobile_regexes{BS} = '242(?:3(?:5[79]|[79]5)|4(?:[2-4][1-9]|5[1-8]|6[2-8]|7\d|81)|5(?:2[45]|3[35]|44|5[1-9]|65|77)|6[34]6|7(?:27|38)|8(?:0[1-9]|1[02-9]|2\d|99))\d{4}';
$fixed_line_regexes{BS} = '242(?:3(?:02|[236][1-9]|4[0-24-9]|5[0-68]|7[347]|8[0-4]|9[2-467])|461|502|6(?:0[1-4]|12|2[013]|[45]0|7[67]|8[78]|9[89])|7(?:02|88))\d{4}';
$mobile_regexes{BS} = '242(?:3(?:5[79]|7[56]|95)|4(?:[23][1-9]|4[1-35-9]|5[1-8]|6[2-8]|7\d|81)|5(?:2[45]|3[35]|44|5[1-46-9]|65|77)|6[34]6|7(?:27|38)|8(?:0[1-9]|1[02-9]|2\d|[89]9))\d{4}';
$fixed_line_regexes{DM} = '767(?:2(?:55|66)|4(?:2[01]|4[0-25-9])|50[0-4]|70[1-3])\d{4}';
$mobile_regexes{DM} = '767(?:2(?:[234689]5|7[5-7])|31[5-7]|61[1-7])\d{4}';
$fixed_line_regexes{GD} = '473(?:2(?:3[0-2]|69)|3(?:2[89]|86)|4(?:[06]8|3[5-9]|4[0-49]|5[5-79]|68|73|90)|63[68]|7(?:58|84)|800|938)\d{4}';
......@@ -5,7 +5,13 @@ use warnings;
use Number::Phone::Country qw(noexport);
use base qw(Number::Phone);
our $VERSION = '1.3';
our $VERSION = '1.4000';
=head1 NAME
Number::Phone::StubCountry - Base class for auto-generated country files
=cut
sub country_code {
my $self = shift;
......@@ -52,6 +58,7 @@ sub _validator {
sub areaname {
my $self = shift;
my $number = $self->{number};
return unless $self->{areanames};
my %map = %{$self->{areanames}};
foreach my $prefix (map { substr($number, 0, $_) } reverse(1..length($number))) {
return $map{$self->country_code().$prefix} if exists($map{$self->country_code().$prefix});
......
......@@ -22,19 +22,19 @@ use base qw(Number::Phone::StubCountry);
use strict;
use warnings;
use utf8;
our $VERSION = 1.20170908113147;
our $VERSION = 1.20180203200231;
my $formatters = [];
my $validators = {
'toll_free' => '',
'mobile' => '4\\d{4}',
'personal_number' => '',
'toll_free' => '',
'fixed_line' => '6[2-467]\\d{3}',
'specialrate' => '([01589]\\d{5})',
'voip' => '',
'personal_number' => '',
'geographic' => '6[2-467]\\d{3}',
'pager' => ''
'pager' => '',
'voip' => ''
};
my %areanames = (
2471 => "Georgetown",
......
......@@ -22,30 +22,34 @@ use base qw(Number::Phone::StubCountry);
use strict;
use warnings;
use utf8;
our $VERSION = 1.20170908113147;
our $VERSION = 1.20180203200231;
my $formatters = [
{
'format' => '$1 $2',
'pattern' => '(\\d{3})(\\d{3})',
'leading_digits' => '
[137-9]|
6[0-8]
',
'pattern' => '(\\d{3})(\\d{3})'
'
},
{
'format' => '$1 $2',
'pattern' => '(\\d{4})(\\d{4})',
'leading_digits' => '180[02]'
},
{
'pattern' => '(\\d{3})(\\d{3})(\\d{3})',
'leading_digits' => '690',
'pattern' => '(\\d{3})(\\d{3})(\\d{3})'
'format' => '$1 $2 $3'
}
];
my $validators = {
'fixed_line' => '[78]\\d{5}',
'geographic' => '[78]\\d{5}',
'specialrate' => '([19]\\d{5})',
'toll_free' => '180[02]\\d{4}',
'fixed_line' => '[78]\\d{5}',
'mobile' => '
(?:
3\\d|
......@@ -55,9 +59,8 @@ my $validators = {
)
)\\d{4}
',
'voip' => '',
'personal_number' => '',
'geographic' => '[78]\\d{5}',
'voip' => '',
'pager' => ''
};
......
......@@ -22,42 +22,47 @@ use base qw(Number::Phone::StubCountry);
use strict;
use warnings;
use utf8;
our $VERSION = 1.20170908113147;
our $VERSION = 1.20180203200232;
my $formatters = [
{
'format' => '$1 $2 $3',
'leading_digits' => '[2-4679][2-8]',
'pattern' => '([2-4679])(\\d{3})(\\d{4})',
'leading_digits' => '[2-4679][2-8]'
'national_rule' => '0$1'
},
{
'format' => '$1 $2 $3',
'leading_digits' => '5',
'pattern' => '(5\\d)(\\d{3})(\\d{4})'
'pattern' => '(5\\d)(\\d{3})(\\d{4})',
'national_rule' => '0$1'
},
{
'format' => '$1 $2 $3',
'leading_digits' => '[479]00',
'pattern' => '([479]00)(\\d)(\\d{5})',
'leading_digits' => '[479]0'
'national_rule' => '$1'
},
{
'pattern' => '([68]00)(\\d{2,9})',
'leading_digits' => '
60|
8
'
'national_rule' => '$1',
'format' => '$1 $2',
'leading_digits' => '[68]00',
'pattern' => '([68]00)(\\d{2,9})'
}
];
my $validators = {
'voip' => '',
'mobile' => '5[024-68]\\d{7}',
'personal_number' => '',
'fixed_line' => '[2-4679][2-8]\\d{6}',
'toll_free' => '
400\\d{6}|
800\\d{2,9}
',
'mobile' => '5[024-68]\\d{7}',
'specialrate' => '(700[05]\\d{5})|(900[02]\\d{5})|(600[25]\\d{5})',
'fixed_line' => '[2-4679][2-8]\\d{6}',
'geographic' => '[2-4679][2-8]\\d{6}',
'pager' => '',
'personal_number' => '',
'geographic' => '[2-4679][2-8]\\d{6}'
'voip' => ''
};
sub new {
......@@ -67,7 +72,10 @@ my $validators = {
my $self = bless({ number => $number, formatters => $formatters, validators => $validators, }, $class);
return $self if ($self->is_valid());
$number =~ s/(^0)//g;
{
no warnings 'uninitialized';
$number =~ s/^(?:0)//;
}
$self = bless({ number => $number, formatters => $formatters, validators => $validators, }, $class);
return $self->is_valid() ? $self : undef;
}
......
......@@ -22,17 +22,19 @@ use base qw(Number::Phone::StubCountry);
use strict;
use warnings;
use utf8;
our $VERSION = 1.20170908113147;
our $VERSION = 1.20180203200232;
my $formatters = [
{
'format' => '$1 $2 $3',
'pattern' => '([2-7]\\d)(\\d{3})(\\d{4})',
'leading_digits' => '[2-7]'
'leading_digits' => '[2-7]',
'national_rule' => '0$1'
}
];
my $validators = {
'specialrate' => '',
'toll_free' => '',
'fixed_line' => '
(?:
[25][0-8]|
......@@ -40,6 +42,15 @@ my $validators = {
6[0-5]
)[2-9]\\d{6}
',
'specialrate' => '',