File Coverage

blib/lib/WWW/Google/API/Base.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package WWW::Google::API::Base;
2              
3 1     1   58153 use strict;
  1         2  
  1         41  
4 1     1   5 use warnings;
  1         2  
  1         602  
5              
6             =head1 NAME
7              
8             WWW::Google::API::Base - Perl client to the Google Base API C<< >>
9              
10             =head1 VERSION
11              
12             version 0.001
13              
14             $Id$
15              
16             =head1 SYNOPSIS
17              
18             use WWW::Google::API::Base;
19              
20             my $file_conf = LoadFile($ENV{HOME}.'/.gapi');
21              
22             my $api_key = $ENV{gapi_key};
23             my $api_user = $ENV{gapi_user};
24             my $api_pass = $ENV{gapi_pass};
25              
26             my $gbase = WWW::Google::API::Base->new( { auth_type => 'ProgrammaticLogin',
27             api_key => $api_key,
28             api_user => $api_user,
29             api_pass => $api_pass },
30             { } );
31              
32             =head1 METHODS
33              
34             =cut
35              
36             our $VERSION = '0.001';
37              
38 1     1   8 use base qw(Class::Accessor);
  1         2  
  1         1097  
39              
40 1     1   3506 use HTTP::Request;
  1         25166  
  1         49  
41 1     1   1069 use LWP::UserAgent;
  1         26444  
  1         37  
42 1     1   676 use WWW::Google::API;
  1         3  
  1         8  
43 1     1   427 use XML::Atom::Entry;
  0            
  0            
44             use XML::Atom::Util qw( nodelist );
45              
46             __PACKAGE__->mk_ro_accessors(qw(namespaces));
47             __PACKAGE__->mk_accessors(qw(client));
48              
49             sub new {
50             my $class = shift;
51            
52             my $client;
53             eval {
54             $client = WWW::Google::API->new('gbase', @_);
55             };
56             if ($@) {
57             my $e = $@;
58             warn $e;
59             }
60             my $self = { client => $client,
61             namespaces => {
62             gm => XML::Atom::Namespace->new( gm => 'http://base.google.com/ns-metadata/1.0'),
63             g => XML::Atom::Namespace->new( g => 'http://base.google.com/ns/1.0' ),
64             batch => XML::Atom::Namespace->new( batch => 'http://schemas.google.com/gdata/batch' ),
65             }
66             };
67              
68             bless($self, $class);
69             return $self;
70             }
71              
72             sub _load_item_type {
73             my $self = shift;
74             my $type = shift;
75              
76            
77             my $ua = LWP::UserAgent->new( agent => 'WWW::Google::API' );
78            
79             my $response = $ua->get($type);
80            
81             die $response->status_line unless $response->is_success;
82            
83             my $entry = XML::Atom::Entry->new(\$response->content);
84            
85             $type = $entry->get($self->{namespaces}{gm}, 'item_type');
86             my @attributes = nodelist($entry->elem, $self->{namespaces}{gm}{uri}, 'attribute');
87             my $attribute_types;
88             foreach my $attribute (@attributes) {
89             my $name = $attribute->getAttribute('name');
90             my $type = $attribute->getAttribute('type');
91             $name =~ s/\s/_/g;
92             $attribute_types->{$name} = $type;
93             }
94             $attribute_types->{'label'} = 'text';
95             return $type, $attribute_types;
96             }
97              
98             =head2 insert
99              
100             $insert_entry = $gbase->insert(
101             'http://www.google.com/base/feeds/itemtypes/en_US/Recipes',
102             { -title => 'He Jingxian\'s chicken',
103             -content => "
Delectable Sichuan specialty
",
104             -link => [
105             { rel => 'alternate',
106             type => 'text/html',
107             href => 'http://localhost/uniqueid'
108             },
109             ],
110             cooking_time => 30,
111             label => [qw(foo bar baz)],
112             main_ingredient => [qw(chicken chili peanuts)],
113             servings => 5,
114             },
115             );
116              
117             $new_id = $insert_entry->id;
118              
119             =cut
120              
121             sub insert {
122             my $self = shift;
123             my $item_type = shift;
124             my $item_parts = shift;
125              
126             my ($type, $gpart_types) = $self->_load_item_type($item_type);
127              
128             $self->client->ua->default_header('content-type', 'application/atom+xml');
129              
130             my $xml = <
131            
132            
133             xmlns:g='http://base.google.com/ns/1.0'>
134            
135             $type
136             EOF
137              
138             for my $key (keys %$item_parts) {
139             if ($key =~ /^-/) {
140             if ($key eq '-content') {
141             $xml .= "\n";
142             $xml .= "$item_parts->{$key}\n";
143             $xml .= "\n";
144             } elsif ($key eq '-link') {
145             if (ref $item_parts->{$key} eq 'ARRAY') {
146             foreach (@{$item_parts->{$key}}) {
147             $xml .= "\n";
148             }
149             } else {
150             $xml .= "\n";
151             }
152             } elsif (ref $item_parts->{$key} eq 'ARRAY') {
153             for my $item (@{$item_parts->{$key}}) {
154             $key =~ s/^-//;
155             $xml .= "<$key type='text'>$item\n";
156             }
157             } else {
158             $key =~ s/^-//;
159             $xml .= "<$key type='text'>".$item_parts->{"-$key"}."\n";
160             }
161             } else {
162             if (ref $item_parts->{$key} eq 'ARRAY') {
163             for my $item (@{$item_parts->{$key}}) {
164             $xml .= "$item\n";
165             }
166             } else {
167             $xml .= "$item_parts->{$key}\n";
168             }
169             }
170             }
171             $xml .= "\n";
172            
173             my $insert_request = HTTP::Request->new( POST => 'http://www.google.com/base/feeds/items',
174             $self->client->ua->default_headers,
175             $xml);
176             my $response;
177             eval {
178             $response = $self->client->do($insert_request);
179             };
180             if ($@) {
181             my $error = $@;
182             die $error;
183             }
184              
185             my $atom = $response->content;
186            
187             my $entry = XML::Atom::Entry->new(\$atom);
188              
189             return $entry
190             }
191              
192             =head2 update
193            
194             $update_entry = $gbase->update(
195             $new_id,
196             { -title => 'He Jingxian\'s chicken',
197             -content => "
Delectable Sichuan specialty
",
198             -link => [
199             { rel => 'alternate',
200             type => 'text/html',
201             href => 'http://localhost/uniqueid'
202             },
203             ],
204             cooking_time => 60,
205             label => [qw(fio bir biz)],
206             main_ingredient => [qw(chicken chili peanuts)],
207             servings => 15,
208             },
209             );
210              
211             =cut
212              
213             sub update {
214             my $self = shift;
215             my $item_id = shift;
216             my $item_parts = shift;
217              
218             my $item = $self->select($item_id);
219              
220             my $item_type = 'http://www.google.com/base/feeds/itemtypes/en_US/';
221             $item_type .= $item->get($self->{namespaces}{g}, 'item_type');
222              
223             my ($type, $gpart_types) = $self->_load_item_type($item_type);
224              
225             $self->client->ua->default_header('content-type', 'application/atom+xml');
226              
227             my $xml = <
228            
229            
230             xmlns:g='http://base.google.com/ns/1.0'>
231            
232             $type
233             EOF
234              
235             for my $key (keys %$item_parts) {
236             if ($key =~ /^-/) {
237             if ($key eq '-content') {
238             $xml .= "\n";
239             $xml .= "$item_parts->{$key}\n";
240             $xml .= "\n";
241             } elsif ($key eq '-link') {
242             if (ref $item_parts->{$key} eq 'ARRAY') {
243             foreach (@{$item_parts->{$key}}) {
244             $xml .= "\n";
245             }
246             } else {
247             $xml .= "\n";
248             }
249             } elsif (ref $item_parts->{$key} eq 'ARRAY') {
250             for my $item (@{$item_parts->{$key}}) {
251             $key =~ s/^-//;
252             $xml .= "<$key type='text'>$item\n";
253             }
254             } else {
255             $key =~ s/^-//;
256             $xml .= "<$key type='text'>".$item_parts->{"-$key"}."\n";
257             }
258              
259             } else {
260             if (ref $item_parts->{$key} eq 'ARRAY') {
261             for my $item (@{$item_parts->{$key}}) {
262             $xml .= "$item\n";
263             }
264             } else {
265             $xml .= "$item_parts->{$key}\n";
266             }
267             }
268             }
269             $xml .= "\n";
270              
271             my $update_request = HTTP::Request->new( PUT => $item_id,
272             $self->client->ua->default_headers,
273             $xml);
274             my $response;
275             eval {
276             $response = $self->client->do($update_request);
277             };
278             if ($@) {
279             my $error = $@;
280             die $error;
281             }
282              
283             my $atom = $response->content;
284            
285             my $entry = XML::Atom::Entry->new(\$atom);
286              
287             return $entry;
288             }
289              
290             =head2 delete
291              
292             my $delete_response;
293             eval {
294             $delete_response =$gbase->delete($new_id);
295             };
296             if ($@) {
297             my $e = $@;
298             die $e->status_line; # HTTP::Response
299             }
300              
301             die "Successfully deleted if $delete_response->code == 200; # HTTP::Response
302              
303             =cut
304              
305             sub delete {
306             my $self = shift;
307             my $item_id = shift;
308             my $delete_request = HTTP::Request->new( DELETE => $item_id,
309             $self->client->ua->default_headers );
310             my $response;
311             eval {
312             $response = $self->client->do($delete_request);
313             };
314             if ($@) {
315             my $error = $@;
316             die $error;
317             }
318             return $response;
319             }
320              
321             =head2 select
322              
323             Currently only supports querying by id
324              
325             my $select_inserted_entry;
326             eval {
327             $select_inserted_entry =$gbase->select($new_id);
328             };
329             if ($@) {
330             my $e = $@;
331             die $e->status_line; # HTTP::Response
332             }
333              
334             =cut
335              
336             sub select {
337             my $self = shift;
338             my $item_id = shift;
339            
340             my $select_request = HTTP::Request->new( GET => $item_id,
341             $self->client->ua->default_headers );
342             my $response;
343             eval {
344             $response = $self->client->do($select_request);
345             };
346             if ($@) {
347             my $error = $@;
348             die $error;
349             }
350              
351             my $atom = $response->content;
352            
353             my $entry = XML::Atom::Entry->new(\$atom);
354              
355             return $entry;
356             }
357              
358             1;