File Coverage

lib/Parse/PhoneNumber.pm
Criterion Covered Total %
statement 61 67 91.0
branch 16 22 72.7
condition 3 3 100.0
subroutine 16 17 94.1
pod 3 4 75.0
total 99 113 87.6


line stmt bran cond sub pod time code
1             package Parse::PhoneNumber;
2 2     2   71503 use strict;
  2         6  
  2         66  
3 2     2   11 use warnings;
  2         3  
  2         61  
4              
5 2     2   11 use Carp;
  2         15  
  2         130  
6              
7 2     2   8 use vars qw[$VERSION $EXT $MINLEN $MIN_US_LENGTH @CCODES];
  2         4  
  2         1865  
8              
9             $VERSION = qw(1.9);
10             $EXT = qr/\s*(?:(?:ext|ex|xt|x)[\s.:]*(\d+))/i;
11              
12             $MINLEN = 7;
13             $MIN_US_LENGTH = 10;
14              
15             @CCODES = qw[
16             1 7 20 27 30 31 32 33 34
17             36 39 40 41 43 44 45 46 47
18             48 49 51 52 53 54 55 56 57
19             58 60 61 62 63 64 65 66 81
20             82 84 86 90 91 92 93 94 95
21             98 212 213 216 218 220 221 222 223
22             224 225 226 227 228 229 230 231 232
23             233 234 235 236 237 238 239 240 241
24             242 243 244 245 246 247 248 249 250
25             251 252 253 254 255 256 257 258 260
26             261 262 263 264 265 266 267 268 269
27             290 291 297 298 299 350 351 352 353
28             354 355 356 357 358 359 370 371 372
29             373 374 375 376 377 378 380 381 385
30             386 387 388 389 420 421 423 500 501
31             502 503 504 505 506 507 508 509 590
32             591 592 593 594 595 596 597 598 599
33             670 672 673 674 675 676 677 678 679
34             680 681 682 683 684 685 686 687 688
35             689 690 691 692 800 808 850 852 853
36             655 856 870 871 872 873 874 878 880
37             881 882 886 960 961 962 963 964 965
38             966 967 968 970 971 972 973 974 975
39             976 977 979 991 992 993 994 995 996
40             998
41             ];
42              
43             =head1 NAME
44              
45             Parse::PhoneNumber - Parse Phone Numbers
46              
47             =head1 SYNOPSIS
48              
49             use Parse::PhoneNumber;
50             my $number = Parse::PhoneNumber->parse( number => $phone );
51            
52             print $number->human;
53              
54             =head1 ABSTRACT
55              
56             Parse phone numbers. Phone number have a defined syntax (to a point),
57             so they can be parsed (to a point).
58              
59             =head1 DESCRIPTION
60              
61             =head2 Methods
62              
63             =head3 new
64              
65             Create a new Parse::PhoneNumber object. Useful if a lot of numbers
66             have to be parsed.
67              
68             =cut
69              
70             sub new {
71 2     2 1 26 return bless {}, shift;
72             }
73              
74             =head3 parse
75              
76             Accepts a list of arguments. C is the phone number. This method
77             will return C and set C on failure. On success, a
78             C object is returned. C will have
79             the country code default to C<1> if none is given. This is due to the fact
80             that most people in the US are clueless about such things.
81              
82             =cut
83              
84             sub parse {
85 110     110 1 47303 my ($class, %data) = @_;
86 110 50       376 croak "No phone number" unless $data{number};
87              
88 110         171 local $_ = $data{number};
89 110         234 s/^\s+//;s/\s+$//;
  110         301  
90              
91 110         543 my %number = (
92             orig => $data{number},
93             cc => undef,
94             num => undef,
95             ext => undef,
96             opensrs => undef,
97             human => undef,
98             );
99            
100            
101              
102 110 50       1268 if ( m/$EXT$/ ) {
103 0 0       0 if ( length $1 > 4 ) {
104 0         0 $class->errstr( "Extension '$1' longer than four digits" );
105 0         0 return undef;
106             } else {
107 0         0 $number{ext} = $1;
108 0         0 s/$EXT$//;
109             }
110             }
111            
112 110         572 s/\D//g;
113 110         204 s/^0+//;
114              
115 110 100       248 if ($data{'assume_us'}) {
116 13 100       31 if (length $_ < $MIN_US_LENGTH) {
117 7         18 $class->errstr("Invalid US number: $data{number}" );
118 7         23 return;
119             } else {
120 6         14 $number{'cc'} = 1;
121 6         14 s/^1//;
122 6         17 $number{'num'} = $_;
123             }
124             } else {
125            
126 97         179 foreach my $len ( 1 .. 3 ) {
127 282 100       647 last if $number{cc};
128            
129 229         379 my $cc = substr $_, 0, $len;
130            
131 229 100       448 if ( grep { $_ eq $cc } @CCODES ) {
  49693         88212  
132 92         157 $number{cc} = $cc;
133 92         1617 s/^$cc//;
134             }
135             }
136            
137 97 100 100     580 if ( $number{cc} && length "$number{cc}$_" >= $MINLEN ) {
138 91         203 $number{num} = "$_";
139             } else {
140 6         28 $class->errstr("Invalid international number: $data{number}" );
141 6         30 return undef;
142             }
143             }
144            
145 97         473 $number{opensrs} = sprintf "+%d.%s", @number{qw[cc num]};
146 97 50       231 $number{opensrs} .= sprintf "x%d", $number{ext} if $number{ext};
147            
148 97         252 $number{human} = sprintf "+%d %s", @number{qw[cc num]};
149 97 50       203 $number{human} .= sprintf " x%d", $number{ext} if $number{ext};
150            
151 97         433 return Parse::PhoneNumber::Number->new( %number );
152             }
153              
154             =head3 errstr
155              
156             Returns the last error reported, or undef if no errors have occured yet.
157              
158             =cut
159              
160             {
161             my $errstr = undef;
162 25 100   25 1 96 sub errstr { $errstr = $_[1] if $_[1]; $errstr }
  25         54  
163 0     0 0 0 sub clear_errstr { $errstr = undef; }
164             }
165              
166             package Parse::PhoneNumber::Number;
167 2     2   11 use strict;
  2         4  
  2         72  
168 2     2   8 use warnings;
  2         4  
  2         437  
169              
170             =head2 Parse::PhoneNumber::Number Objects
171              
172             The objects returned on a successful parse.
173              
174             =cut
175              
176             sub new {
177 97     97   460 my ($class, %data) = @_;
178 97         704 return bless \%data, $class;
179             }
180              
181             =head3 orig
182              
183             The original string passed to C.
184              
185             =head3 cc
186              
187             The Country Code
188              
189             =head3 num
190              
191             The phone number, including the trunk pointer, area code, and
192             subscriber number.
193              
194             =head3 ext
195              
196             An extension, if one is present.
197              
198             =head3 opensrs
199              
200             The format an OpenSRS Registrar must make a phone number for some
201             TLDs.
202              
203             =head3 human
204              
205             Human readable format.
206              
207             =cut
208              
209 194     194   700 sub orig { $_[0]->{orig} }
210 194     194   53528 sub cc { $_[0]->{cc} }
211 97     97   776 sub num { $_[0]->{num} }
212 194     194   588 sub ext { $_[0]->{ext} }
213 194     194   1064 sub opensrs { $_[0]->{opensrs} }
214 194     194   997 sub human { $_[0]->{human} }
215              
216             1;
217              
218             __END__