File Coverage

blib/lib/WebService/Zusaar.pm
Criterion Covered Total %
statement 113 124 91.1
branch 30 38 78.9
condition 8 20 40.0
subroutine 19 19 100.0
pod 4 4 100.0
total 174 205 84.8


line stmt bran cond sub pod time code
1             package WebService::Zusaar;
2              
3 4     4   106113 use warnings;
  4         8  
  4         116  
4 4     4   19 use strict;
  4         7  
  4         110  
5 4     4   20 use Carp;
  4         11  
  4         393  
6 4     4   958 use utf8;
  4         18  
  4         18  
7              
8 4     4   3511 use version;
  4         8628  
  4         35  
9             our $VERSION = qv('0.0.4');
10              
11 4     4   378 use base qw/Class::Accessor/;
  4         10  
  4         4236  
12 4     4   13736 use Data::Recursive::Encode;
  4         63017  
  4         147  
13 4     4   4244 use DateTime::Format::ISO8601;
  4         1032265  
  4         350  
14 4     4   4127 use Hash::AsObject;
  4         3386  
  4         24  
15 4     4   4246 use JSON;
  4         56511  
  4         24  
16 4     4   7853 use LWP::UserAgent;
  4         246483  
  4         153  
17 4     4   41 use URI;
  4         9  
  4         4337  
18              
19             # Accessors
20             __PACKAGE__->mk_accessors( qw/ iter / );
21              
22             # Constructor
23             sub new {
24 3     3 1 154984 my ($class, %param) = @_;
25 3         31 my $self = bless({}, $class);
26              
27             # Parameter - Base URL (API Endpoint)
28 3 100       35 if(defined($param{baseurl})){
29 2         60 $self->{baseurl} = $param{baseurl};
30 2         22 delete $param{baseurl};
31             }else{
32 1         12 $self->{baseurl} = 'http://www.zusaar.com/api/';
33             }
34              
35             # Parameter - Encoding (Char-set)
36 3 100       33 if(defined($param{encoding})){
37 1         10 $self->{encoding} = $param{encoding};
38 1         8 delete $param{encoding};
39             }
40              
41             # Parameter - Automatic next page fetch
42 3 50 33     34 if(defined($param{disable_nextpage_fetch}) && $param{disable_nextpage_fetch}){
43 0         0 $self->{nextpage_fetch} = 0;
44 0         0 delete $param{disable_nextpage_fetch};
45             }else{
46 3         11 $self->{nextpage_fetch} = 1;
47             }
48              
49             # Parameter - Timeout
50 3   50     199 $param{timeout} = $param{timeout} || 10;
51              
52             # Parameter - UserAgent string
53 3   33     139 $param{agent} = $param{agent} || __PACKAGE__.'/'.$VERSION;
54              
55             # ----------
56              
57             # Prepare a LWP::UA instance
58 3         170 $self->{ua} = LWP::UserAgent->new(%param);
59              
60             # Prepare a Date parser instance
61 3         22301 $self->{datetime_parser} = DateTime::Format::ISO8601->new();
62              
63             # Prepare events store array
64 3         642 $self->{events} = [];
65              
66 3         17 $self->{current_request_path} = '';
67 3         12 $self->{current_query} = ();
68 3         30 return $self;
69             }
70              
71             # Fetch events
72             sub fetch {
73 3     3 1 45 my ($self, $request_path, %query) = @_;
74              
75 3         10 my $is_auto_fetch = 0;
76 3 50       99 if(defined($query{_is_auto_fetch})){
77 0         0 $is_auto_fetch = 1;
78 0         0 delete $query{_is_auto_fetch};
79             }
80              
81 3         8 $self->{current_request_path} = $request_path;
82 3   50     63 $self->{current_query} = \%query || {};
83 3   50     81 $self->{current_query}->{count} = $self->{current_query}->{count} || 10; # Each fetch num of item
84              
85             # Request
86 3         12 my $url = $self->_generate_get_url($self->{baseurl}.$request_path.'/', %{$self->{current_query}});
  3         44  
87 3         269 my $response = $self->{ua}->get($url);
88 3 50       507476 unless($response->is_success){
89 0         0 die 'Fetch error: '.$response->status_line;
90             }
91              
92             # Decode JSON
93 3         227 my $js_hash = JSON->new->utf8->decode($response->content);
94              
95             # Encoding
96 3 100       1417 if(defined($self->{encoding})){
97 1         55 $js_hash = Data::Recursive::Encode->encode($self->{encoding}, $js_hash);
98             }
99              
100             # Initialize the events store array
101 3 50       819 unless($is_auto_fetch){ # If not auto-fetch...
102 3         18 $self->{events} = [];
103             }
104              
105             # Store events
106 3         9 foreach my $item(@{$js_hash->{event}}){
  3         14  
107 5         10 my $item_id = $item->{event_id};
108 5         8 push(@{$self->{events}}, $item);
  5         17  
109             }
110              
111             # Reset iterator
112 3 50       15 unless($is_auto_fetch){
113 3         29 $self->iter(0);
114             }
115              
116 3         198 return;
117             }
118              
119             # Put to next a Iterator
120             sub next {
121 9     9 1 161114 my $self = shift;
122 9   50     75 my $_is_disable_autofetch = shift || 0;
123              
124 9         48 my $i = $self->iter();
125 9 50       144 if($i < 0){ $i = 0; }
  0         0  
126              
127 9 100       17 if($i < @{$self->{events}}){
  9         49  
128             # Next one
129 6         26 $self->iter($i + 1);
130             # Return one event object
131 6         92 return $self->_generate_event_object($self->{events}->[$i]);
132             }else{
133             # Fetch next page automatically
134 3 50 33     76 if($self->{nextpage_fetch} == 1 && $_is_disable_autofetch == 0 && @{$self->{events}} % $self->{current_query}->{count} == 0){
  3   33     28  
135 0         0 $self->{current_query}->{start} = $i;
136 0         0 $self->{current_query}->{_is_auto_fetch} = 1;
137             # Auto fetch
138 0         0 $self->fetch($self->{current_request_path}, %{$self->{current_query}});
  0         0  
139 0         0 return $self->next(1);
140             }
141             }
142 3         10 return;
143             }
144              
145             # prev a Iterator
146             sub prev {
147 7     7 1 19232 my $self = shift;
148              
149 7         35 my $i = $self->iter() - 1;
150              
151 7 100       97 if(0 <= $i){
152             # Prev one
153 5         17 $self->iter($i);
154             # Return one event object
155 5         80 return $self->_generate_event_object($self->{events}->[$i]);
156             }
157 2         8 return;
158             }
159              
160             # Generate Event object from Hash
161             sub _generate_event_object {
162 11     11   24 my ($self, $hash) = @_;
163            
164             # Date parse
165 11 100       194 unless(defined($hash->{started})){
166 5 100       61 $hash->{started} = defined($hash->{started_at}) ? $self->{datetime_parser}->parse_datetime($hash->{started_at}) : undef;
167             }
168              
169 11 100       3842 unless(defined($hash->{ended})){
170 5 100       32 $hash->{ended} = defined($hash->{ended_at}) ? $self->{datetime_parser}->parse_datetime($hash->{ended_at}) : undef;
171             }
172              
173 11 100       2165 unless(defined($hash->{updated})){
174 5 50       63 $hash->{updated} = defined($hash->{updated_at}) ? $self->{datetime_parser}->parse_datetime($hash->{updated_at}) : undef;
175             }
176              
177             # If fetch event/users
178 11 100       2842 if(defined($hash->{users})){
179 1         2 foreach my $user(@{$hash->{users}}){
  1         4  
180 3         75 $user = $self->_generate_event_user_object($user);
181             }
182             }
183              
184 11         193 return Hash::AsObject->new($hash);
185             }
186              
187             # Generate Event/User object from Hash
188             sub _generate_event_user_object {
189 3     3   6 my ($self, $hash) = @_;
190            
191 3         70 return Hash::AsObject->new($hash);
192             }
193              
194             # Generate URL from URL And Query parameters
195             sub _generate_get_url {
196 3     3   14 my ($self, $url, %params) = @_;
197 3         69 my $uri = URI->new($url);
198 3         43108 $uri->query_form(\%params);
199 3         852 return $uri->as_string();
200             }
201              
202             1;
203             __END__
204             =head1 NAME
205              
206             WebService::Zusaar - The Zusaar API wrapper module for perl
207              
208             =head1 SYNOPSIS
209              
210             use WebService::Zusaar;
211            
212             my $zusaar = WebService::Zusaar->new( encoding => 'utf8' );
213            
214             # Request event
215             $zusaar->fetch( 'event', keyword => 'Kansai.pm' );
216            
217             # Print each events title
218             while ( my $event = $zusaar->next ){
219             print $event->title . "(id:". $event->event_id .")\n";
220             }
221              
222             # Request event/user
223             $zusaar->fetch( 'event/user', event_id => '476003' );
224              
225             while ( my $event = $zusaar->next ){
226             # Print each users of event
227             foreach my $user( @{$event->users} ){
228             print $user->nickname . "\n";
229             }
230             }
231              
232             =head1 INSTALLATION (from GitHub)
233              
234             $ git clone git://github.com/mugifly/p5-WebService-Zusaar.git
235             $ cpanm ./p5-WebService-Zusaar
236              
237             =head1 METHODS
238              
239             =head2 new ( [%params] )
240              
241             Create an instance of WebService::Zusaar.
242              
243             %params = (optional) LWP::UserAgent options, and encoding (example: encoding => 'utf8').
244              
245             =head2 fetch ( $api_path [, %params] )
246              
247             Send request to Zusaar API.
248             Also, this method has supported a fetch like 'Auto-Pager'.
249              
250             =over 4
251              
252             =item * $api_path = Path of request to Zusaar API. Currently available: "event" or "event/user".
253              
254             =item * %params = Query parameter.
255              
256             =back
257              
258             About the query, please see: http://www.zusaar.com/doc/api.html
259              
260             =head3 About the fetch like 'AutoPager'
261              
262             You can fetch all search results, by such as this code:
263              
264             # Request event
265             $zusaar->fetch( 'event' );
266            
267             # Print each events title
268             while ( my $event = $zusaar->next ){
269             print $event->title . "\n";
270             }
271              
272             In the case of default, you can fetch max 10 items by single request to Zusaar API.
273             However, this module is able to fetch all results by repeat request, automatically.
274              
275             Also, you can disable this function, by specifying an option(disable_nextpage_fetch => 1) when call a constructor:
276              
277             my $zusaar = WebService::Zusaar->new(disable_nextpage_fetch => 1);
278              
279             # Request event
280             $zusaar->fetch( 'event' );
281            
282             # Print each events title
283             while ( my $event = $zusaar->next ){
284             print $event->title . "\n";
285             }
286              
287             In this case, you can fetch max 10 items.
288              
289             But also, you can fetch more items by causing a 'fetch' method again with 'start' parameter:
290              
291             # Request the event of the remaining again
292             $zusaar->fetch( 'event', start => 10 ); # Fetch continue after 10th items.
293              
294             =head2 next
295              
296             Get a next item, from the fetched items in instance.
297              
298             The item that you got is an object.
299              
300             You can use the getter-methods (same as a API response fields name, such as: 'title', 'event_id', 'catch', etc...)
301              
302             my $event = $zusaar->next; # Get a next one item
303             print $event->title . "\n"; # Output a 'title' (included in this item)
304              
305             In addition, you can also use a following getter-methods : 'started', 'ended', 'updated'.
306              
307             So, these methods return the each object as the 'DateTime::Format::ISO8601', from 'started_at', 'ended_at' and 'updated_at' field.
308              
309             =head2 prev
310              
311             Get a previous item, from the fetched items in instance.
312              
313             =head2 iter
314              
315             set or get a position of iterator.
316              
317             =head1 SEE ALSO
318              
319             L<https://github.com/mugifly/p5-WebService-Zusaar/> - Your feedback is highly appreciated.
320              
321             L<DateTime::Format::ISO8601>
322              
323             L<Hash::AsObject>
324              
325             L<LWP::UserAgent>
326              
327             L<WebService::ATND> - https://github.com/ytnobody/WebService-ATND/
328             (Maybe you can use this library with an almost similar code.)
329              
330             =head1 COPYRIGHT AND LICENSE
331              
332             Copyright (C) 2013, Masanori Ohgita (http://ohgita.info/).
333              
334             This library is free software; you can redistribute it and/or modify
335             it under the same terms as Perl itself.
336              
337             I wrote this library with referred to the library that was written by L<ytnobody|https://github.com/ytnobody>. Thank you.
338              
339             Thanks, Perl Mongers & CPAN authors.