File Coverage

blib/lib/Geo/Coder/Mapquest.pm
Criterion Covered Total %
statement 47 89 52.8
branch 19 56 33.9
condition 5 9 55.5
subroutine 11 14 78.5
pod 5 5 100.0
total 87 173 50.2


line stmt bran cond sub pod time code
1             package Geo::Coder::Mapquest;
2              
3 3     3   68495 use strict;
  3         6  
  3         98  
4 3     3   15 use warnings;
  3         4  
  3         84  
5              
6 3     3   16 use Carp qw(croak);
  3         8  
  3         284  
7 3     3   2791 use Encode ();
  3         36863  
  3         67  
8 3     3   3110 use JSON;
  3         57356  
  3         18  
9 3     3   3938 use LWP::UserAgent;
  3         184271  
  3         128  
10 3     3   35 use URI;
  3         6  
  3         98  
11 3     3   16 use URI::Escape qw(uri_unescape);
  3         5  
  3         9645  
12              
13             our $VERSION = '0.06';
14             $VERSION = eval $VERSION;
15              
16             sub new {
17 7     7 1 2804 my ($class, @params) = @_;
18 7 100       28 my %params = (@params % 2) ? (apikey => @params) : @params;
19              
20 7 100       194 my $key = $params{apikey} or croak q('apikey' is required);
21              
22 6         14 my $self = bless \ %params, $class;
23 6 50       25 $self->{key} = uri_unescape($key),
    50          
24              
25             $self->{host} = $params{host} ? $params{host}
26             : ($params{open} ? 'open' : 'www') . '.mapquestapi.com';
27              
28 6   66     138 $self->ua(
29             $params{ua} || LWP::UserAgent->new(agent => "$class/$VERSION")
30             );
31              
32 6 50       23 if ($self->{debug}) {
    100          
    50          
33 2     0   6 my $dump_sub = sub { $_[0]->dump(maxlength => 0); return };
  0         0  
  0         0  
34 2         6 $self->ua->set_my_handler(request_send => $dump_sub);
35 2         139 $self->ua->set_my_handler(response_done => $dump_sub);
36             }
37             elsif (exists $self->{compress} ? $self->{compress} : 1) {
38 4         8 $self->ua->default_header(accept_encoding => 'gzip,deflate');
39             }
40              
41 6 100 66     241 croak q('https' requires LWP::Protocol::https)
42             if $self->{https} and not $self->ua->is_protocol_supported('https');
43              
44 5         17 return $self;
45             }
46              
47 0     0 1 0 sub response { $_[0]->{response} }
48              
49             sub ua {
50 15     15 1 6007 my ($self, $ua) = @_;
51 15 100       34 if ($ua) {
52 6 50 33     46 croak q('ua' must be (or derived from) an LWP::UserAgent')
53             unless ref $ua and $ua->isa(q(LWP::UserAgent));
54 6         12 $self->{ua} = $ua;
55             }
56 15         42 return $self->{ua};
57             }
58              
59             sub geocode {
60 0     0 1 0 my ($self, @params) = @_;
61 0 0       0 my %params = (@params % 2) ? (location => @params) : @params;
62              
63 0 0       0 my $location = $params{location} or return;
64 0         0 $location = Encode::encode('utf-8', $location);
65              
66 0         0 my $country = $params{country};
67              
68 0         0 my $uri = URI->new("http://$self->{host}/geocoding/v1/address");
69 0 0       0 $uri->query_form(
70             key => $self->{key},
71             location => $location,
72             $country ? (adminArea1 => $country) : (),
73             );
74 0 0       0 $uri->scheme('https') if $self->{https};
75              
76 0         0 my $res = $self->{response} = $self->ua->get($uri);
77 0 0       0 return unless $res->is_success;
78              
79             # Change the content type of the response from 'application/json' so
80             # HTTP::Message will decode the character encoding.
81 0         0 $res->content_type('text/plain');
82              
83 0         0 my $data = eval { from_json($res->decoded_content) };
  0         0  
84 0 0       0 return unless $data;
85              
86 0 0       0 my @results = @{ $data->{results}[0]{locations} || [] };
  0         0  
87 0 0       0 if (@results) {
88 0 0       0 $#results = 0 unless wantarray;
89              
90             # Keep the location data structure flat.
91 0         0 my $provided = $data->{results}[0]{providedLocation}{location};
92 0         0 $_->{providedLocation} = $provided for @results;
93             }
94              
95 0 0       0 return wantarray ? @results : $results[0];
96             }
97              
98             sub batch {
99 1     1 1 13 my ($self, @params) = @_;
100 1 50       4 my %params = (@params % 2) ? (locations => @params) : @params;
101              
102 1 50       3 my $locations = $params{locations} or return;
103 1 50       5 $locations = \@params unless 'ARRAY' eq ref $locations;
104 1 50       150 croak 'too many locations- limit is 100' if 100 < @$locations;
105              
106 0           $_ = Encode::encode('utf-8', $_) for @$locations;
107              
108 0           my $uri = URI->new("http://$self->{host}/geocoding/v1/batch");
109 0           $uri->query_form(
110             key => $self->{key},
111             location => $locations,
112             );
113 0 0         $uri->scheme('https') if $self->{https};
114              
115 0           my $res = $self->{response} = $self->ua->get($uri);
116 0 0         return unless $res->is_success;
117              
118             # Change the content type of the response from 'application/json' so
119             # HTTP::Message will decode the character encoding.
120 0           $res->content_type('text/plain');
121              
122 0           my $data = eval { from_json($res->decoded_content) };
  0            
123 0 0         return unless $data;
124              
125 0           my @results;
126 0 0         for my $result (@{ $data->{results} || [] }) {
  0            
127 0           my $locations = $result->{locations};
128              
129             # Keep the location data structure flat.
130 0           my $provided = $result->{providedLocation}{location};
131 0           $_->{providedLocation} = $provided for @$locations;
132              
133 0           push @results, $locations;
134             }
135              
136 0           return @results;
137             }
138              
139              
140             1;
141              
142             __END__