line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package WWW::Socrata; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
24544
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
40
|
|
4
|
1
|
|
|
1
|
|
7
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
30
|
|
5
|
1
|
|
|
1
|
|
489
|
use WWW::Curl::Easy; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use JSON; |
7
|
|
|
|
|
|
|
use URI::Escape; |
8
|
|
|
|
|
|
|
use Carp; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
13
|
|
|
|
|
|
|
my $class = shift; |
14
|
|
|
|
|
|
|
my $rh_params = shift; |
15
|
|
|
|
|
|
|
my $self = {}; |
16
|
|
|
|
|
|
|
bless $self, ref $class || $class; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
if (! $rh_params) { |
19
|
|
|
|
|
|
|
$rh_params = {}; |
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
$self->_initialize($rh_params); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
return $self; |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
sub _initialize{ |
28
|
|
|
|
|
|
|
my ($self, $rh_params) = @_; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
! defined $rh_params->{base_url} |
31
|
|
|
|
|
|
|
&& croak "base_url parameter required to create new Socrata object"; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# base URL |
34
|
|
|
|
|
|
|
#The base URL for this Socrata API, ex: http://data.medicare.gov/api or http://www.socrata.com/api |
35
|
|
|
|
|
|
|
$self->{base_url} = $rh_params->{base_url} || "http://nycopendata.socrata.com/api"; |
36
|
|
|
|
|
|
|
# app token |
37
|
|
|
|
|
|
|
$self->{app_token} = $rh_params->{app_token} || ""; |
38
|
|
|
|
|
|
|
# username and password used for authentication requests |
39
|
|
|
|
|
|
|
$self->{username} = $rh_params->{username} || ""; |
40
|
|
|
|
|
|
|
$self->{password} = $rh_params->{password} || ""; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub get{ |
46
|
|
|
|
|
|
|
my ($self, $path, $rh_params) = @_; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
if (! $path || $path eq ""){ warn "you must define a path"; } |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# use passed in path for dataset |
51
|
|
|
|
|
|
|
my $full_url = $self->{base_url} . $path; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
#define default headers to send |
54
|
|
|
|
|
|
|
my @headers = ( |
55
|
|
|
|
|
|
|
'Accept: application/json', |
56
|
|
|
|
|
|
|
'Content-type: application/json', |
57
|
|
|
|
|
|
|
"X-App-Token: " . $self->{app_token}, |
58
|
|
|
|
|
|
|
); |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
#define parameters |
61
|
|
|
|
|
|
|
my $qstring; |
62
|
|
|
|
|
|
|
my @paramlist; |
63
|
|
|
|
|
|
|
foreach (keys(%$rh_params)){ |
64
|
|
|
|
|
|
|
push (@paramlist,join("=", uri_escape($_), uri_escape($rh_params->{$_}))); |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
$qstring = join("&", @paramlist); |
67
|
|
|
|
|
|
|
if ($qstring ne ""){ |
68
|
|
|
|
|
|
|
$full_url .= "?" .$qstring; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# initialize curl object and set options |
72
|
|
|
|
|
|
|
my $curl = WWW::Curl::Easy->new(); |
73
|
|
|
|
|
|
|
$curl->setopt(CURLOPT_HEADER, 1); |
74
|
|
|
|
|
|
|
$curl->setopt(CURLOPT_URL, $full_url); |
75
|
|
|
|
|
|
|
$curl->setopt(CURLOPT_HTTPHEADER, \@headers); |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# add suthentication if username and password are defined |
78
|
|
|
|
|
|
|
if ($self->{username} ne ""){ |
79
|
|
|
|
|
|
|
$curl->setopt(CURLOPT_USERPWD, $self->{username} . ":" . $self->{password}); |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
#define reposnse varaiable |
83
|
|
|
|
|
|
|
my $response_body; |
84
|
|
|
|
|
|
|
$curl->setopt(CURLOPT_WRITEDATA,\$response_body); |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# perform the curl |
87
|
|
|
|
|
|
|
my $retcode = $curl->perform; |
88
|
|
|
|
|
|
|
my $obj_response = {}; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# if good response |
91
|
|
|
|
|
|
|
if ($retcode == 0){ |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# remove headers from output |
94
|
|
|
|
|
|
|
my @response = split("\n",$response_body); |
95
|
|
|
|
|
|
|
my $count =0; |
96
|
|
|
|
|
|
|
foreach (@response){ |
97
|
|
|
|
|
|
|
if ($_ !~ /{/){ |
98
|
|
|
|
|
|
|
$count++; |
99
|
|
|
|
|
|
|
} else{ |
100
|
|
|
|
|
|
|
last; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
for (my $i=0; $i<$count; $i++){ |
104
|
|
|
|
|
|
|
shift @response; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
$response_body = join("\n", @response); |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
$obj_response = decode_json($response_body); |
109
|
|
|
|
|
|
|
return $obj_response; |
110
|
|
|
|
|
|
|
} else { |
111
|
|
|
|
|
|
|
croak "An error happened: " . $curl->strerror($retcode) . " " . $curl->errbuf . "\n"; |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 NAME |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
WWW::Socrata - The great new WWW::Socrata! |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head1 VERSION |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Version 0.02 |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 SYNOPSIS |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
use WWW::Socrata; |
126
|
|
|
|
|
|
|
my %options = ( |
127
|
|
|
|
|
|
|
base_url => "https://nycopendata.socrata.com", |
128
|
|
|
|
|
|
|
); |
129
|
|
|
|
|
|
|
my $socrata = new WWW::Socrata(\%options); |
130
|
|
|
|
|
|
|
my $rh_result = $socrata->get("/api/views/74cu-ncm4/rows.json", {}); |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head1 DESCRIPTION |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
This library provides a simple wrapper for accessing some of the features of the Socrata Open Data API from PHP. Currently it only supports HTTP GET operations, but in the future it will support other methods as well. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
The library is very simple. To access the Socrata API, you first instantiate a "Socrata" object, passing in the API base URL for the data site you wish to access. The Base URL is always the URL for the root of the datasite, with "/api" added to the path (ex: http://www.socrata.com/api or http://data.medicare.gov/api). Then you can use its included methods to make simple API calls: |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
This library provides an interface to the SODA Publisher API. If you're new to all this, you may want to brush up on the getting started guide. |
140
|
|
|
|
|
|
|
dev.socrata.com/publisher/getting-started |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
If you're curious about how things work under the hood, you can also browse the API documentation directly. |
143
|
|
|
|
|
|
|
http://opendata.socrata.com/api/docs/ |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head1 OPTIONS |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
Additional options when creating the new Socrata object |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
use WWW::Socrata; |
150
|
|
|
|
|
|
|
my %options = ( |
151
|
|
|
|
|
|
|
base_url => "https://nycopendata.socrata.com", |
152
|
|
|
|
|
|
|
app_token => "", #optional |
153
|
|
|
|
|
|
|
username => "", #optional for authenticated requests |
154
|
|
|
|
|
|
|
password => "", #optional for authenticated requests |
155
|
|
|
|
|
|
|
); |
156
|
|
|
|
|
|
|
my $socrata = new WWW::Socrata(\%options); |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
You may also add additional criteria on the get function, for searching or retrieving subsets of the data |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
my $rh_result = $socrata->get("/api/views/74cu-ncm4/rows.json", |
161
|
|
|
|
|
|
|
{ |
162
|
|
|
|
|
|
|
"method"=>"getRows", |
163
|
|
|
|
|
|
|
"start"=>120, |
164
|
|
|
|
|
|
|
"length" =>60, |
165
|
|
|
|
|
|
|
}); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head1 AUTHOR |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Benjamin Marcus, C<< >> |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head1 BUGS |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
175
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
176
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 SUPPORT |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
perldoc WWW::Socrata |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
You can also look for information at: |
187
|
|
|
|
|
|
|
http://www.socrata.org |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=over 4 |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker (report bugs here) |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
L |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
L |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item * CPAN Ratings |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
L |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item * Search CPAN |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
L |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=back |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
Copyright 2012 Benjamin Marcus. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
218
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
219
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
1; # End of WWW::Socrata |