File Coverage

blib/lib/WWW/FreshBooks/API.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package WWW::FreshBooks::API;
2 1     1   23472 use warnings;
  1         3  
  1         34  
3 1     1   8 use strict;
  1         2  
  1         38  
4 1     1   7 use Carp;
  1         3  
  1         83  
5              
6 1     1   994 use version; our $VERSION = qv('0.1.0');
  1         2438  
  1         6  
7              
8 1     1   95 use base qw/Class::Accessor::Children::Fast/;
  1         2  
  1         1106  
9             __PACKAGE__->mk_accessors( qw/svc_url auth_token method m_api m_func r_args ua xs response results item_class item_fields/ );
10             __PACKAGE__->mk_child_accessors(
11             Response => [qw(http ref content as_string status)],
12             Results => [qw(page per_page pages total fields items iterator)],
13             );
14              
15 1     1   7059 use Iterator::Simple qw(iter);
  1         6429  
  1         94  
16 1     1   1483 use LWP::UserAgent;
  1         64930  
  1         39  
17 1     1   585 use XML::Simple;
  0            
  0            
18              
19             sub new {
20             my $class = shift;
21             my $args = shift;
22            
23             if ((!exists $args->{'svc_url'}) || (!exists $args->{'auth_token'})) {
24             warn "Undefined svc_url or auth_token.";
25             return;
26             }
27              
28             $class = ref($class) || $class;
29             my $self = bless {}, $class;
30              
31             $self->init($args);
32             return $self;
33             }
34              
35             sub init {
36             my $self = shift;
37             my $args = shift;
38              
39             $self->svc_url($args->{'svc_url'});
40             $self->auth_token($args->{'auth_token'});
41             $self->ua(LWP::UserAgent->new(agent => $self->_agent, timeout => 30));
42             $self->xs(XML::Simple->new(RootName => ''));
43              
44             return $self;
45             }
46              
47             sub call {
48             my $self = shift;
49             my $method = shift;
50             my $args = shift;
51              
52             $self->r_args($args);
53             $self->_parse_method($method);
54              
55             my $req = HTTP::Request->new(POST => $self->svc_url);
56             $req->authorization_basic($self->auth_token, "X");
57             $req->content($self->_rxml);
58              
59             print STDERR Data::Dumper->Dump([$req]);
60             my $resp = $self->ua->request($req);
61             if ($resp->code != 200) {
62             return(0,$resp);
63             }
64              
65             my $ref = $self->xs->xml_in($resp->content, KeyAttr => []);
66             my $response = WWW::FreshBooks::API::Response->new({
67             http => $resp,
68             ref => $ref,
69             status => $ref->{'status'},
70             content => $resp->content,
71             as_string => $resp->as_string,
72             });
73             $self->response($response);
74              
75             my $robj;
76             my $ritems;
77             my $item_class;
78             unless (($self->m_func eq "list") || (!exists $ref->{$self->m_api})) {
79             $self->_mk_item_class($ref->{$self->m_api});
80             $ritems = [ $ref->{$self->m_api} ];
81             $robj = {};
82             }
83              
84             unless (defined $item_class) {
85             foreach my $k(keys %{$ref}) {
86             my $v = $ref->{$k};
87             if ((ref $v eq "HASH") && (exists $v->{$self->m_api})) {
88             $robj = $v;
89              
90             $self->_mk_item_class($v->{$self->m_api});
91             $ritems = $v->{$self->m_api};
92             }
93             }
94             }
95             $item_class = $self->item_class;
96              
97             my $items;
98             my $fmap = $self->item_fields;
99             my $fields = $fmap->{$item_class};
100             foreach my $i(@{$ritems}) {
101             my $item = $item_class->new($i);
102             push(@{$items}, $item);
103             }
104              
105             $robj->{'items'} = $items;
106             $robj->{'fields'} = $fields;
107             $robj->{'iterator'} = iter($items);
108             my $results = WWW::FreshBooks::API::Results->new($robj);
109             $self->results($results);
110              
111             return (wantarray) ? ($ref,$resp) : $self->results;
112             }
113              
114             sub _mk_item_class {
115             my $self = shift;
116             my $tmpl = shift;
117              
118             $tmpl = $$tmpl[0] if ref($tmpl) eq "ARRAY";
119             my $fields = [keys %{$tmpl}];
120             my $item_name = ucfirst($self->m_api);
121             __PACKAGE__->mk_child_accessors($item_name => $fields);
122             my $class = __PACKAGE__ . "::" . $item_name;
123              
124             $self->item_class($class);
125             my $item_fields = $self->item_fields;
126             $item_fields->{$class} = $fields;
127             $self->item_fields($item_fields);
128              
129             return $self;
130             }
131              
132             sub _parse_method {
133             my $self = shift;
134             my $method = shift;
135              
136             $self->method($method);
137             my ($api, $func) = split(/\./, $method);
138             $self->m_api($api);
139             $self->m_func($func);
140              
141             return $self;
142             }
143              
144             sub _rxml {
145             my $self = shift;
146              
147             my $w = $self->_xwrap();
148             my $x = $self->xs->xml_out($self->r_args, RootName => $self->_root_name);
149             my $fnr = {
150             '__M__' => $self->method,
151             '__X__' => $x,
152             };
153              
154             foreach my $f(keys %{$fnr}) {
155             $w =~ s/$f/$fnr->{$f}/g;
156             }
157             return $w;
158             }
159              
160             sub _root_name {
161             my $self = shift;
162             my $root_name = (($self->m_func eq "create") || ($self->m_func eq "update")) ? $self->m_api : "";
163             return $root_name;
164             }
165              
166             sub _xwrap {
167             return qq{
168            
169             __X__
170             };
171             }
172              
173             sub _agent { __PACKAGE__ . "/" . $VERSION }
174              
175             1;
176              
177             __END__