File Coverage

lib/Business/Fixflo/Resource.pm
Criterion Covered Total %
statement 62 70 88.5
branch 7 10 70.0
condition 9 14 64.2
subroutine 16 18 88.8
pod 3 4 75.0
total 97 116 83.6


line stmt bran cond sub pod time code
1             package Business::Fixflo::Resource;
2              
3             =head1 NAME
4              
5             Business::Fixflo::Resource
6              
7             =head1 DESCRIPTION
8              
9             This is a base class for Fixflo resource classes, it implements common
10             behaviour. You shouldn't use this class directly, but extend it instead.
11              
12             =cut
13              
14 16     16   8383 use strict;
  16         37  
  16         482  
15 16     16   80 use warnings;
  16         34  
  16         372  
16              
17 16     16   78 use Moo;
  16         39  
  16         94  
18 16     16   5661 use Carp qw/ confess carp /;
  16         43  
  16         1047  
19 16     16   118 use JSON ();
  16         42  
  16         315  
20 16     16   83 use Try::Tiny;
  16         34  
  16         985  
21 16     16   528 use Business::Fixflo::Paginator;
  16         41  
  16         20173  
22              
23             =head1 ATTRIBUTES
24              
25             client
26             url
27             url_no_id
28              
29             =cut
30              
31             has client => (
32             is => 'ro',
33             isa => sub {
34             confess( "$_[0] is not a Business::Fixflo::Client" )
35             if ref $_[0] ne 'Business::Fixflo::Client';
36             },
37             required => 1,
38             );
39              
40             has [ qw/ url / ] => (
41             is => 'rw',
42             lazy => 1,
43             default => sub {
44             my ( $self ) = @_;
45             join( '/',$self->url_no_id,$self->Id )
46             },
47             );
48              
49             has 'warn_unknown_attributes' => (
50             is => 'rw',
51             isa => sub { $_[0] || ! $_[0] },
52             default => 0,
53             );
54              
55             has [ qw/ url_no_id / ] => (
56             is => 'rw',
57             lazy => 1,
58             default => sub {
59             my ( $self ) = @_;
60             return join(
61             '/',
62             $self->client->base_url . $self->client->api_path,
63             ( split( ':',ref( $self ) ) )[-1],
64             );
65             },
66             );
67              
68             =head1 METHODS
69              
70             =head2 to_hash
71              
72             Returns a hash representation of the object.
73              
74             my %data = $Issue->to_hash;
75              
76             =head2 to_json
77              
78             Returns a json string representation of the object.
79              
80             my $json = $Issue->to_json;
81              
82             =head2 get
83              
84             Populates the object with its attributes (calls the API)
85              
86             $Issue->get
87              
88             As the data returned in the call to list objects does not contain the full data
89             of the objects (it only contains lightweight information, such as the URLs of
90             the objects you are interested in) you need to call the ->get method to
91             populate the attributes on an object. Really the Paginator just contains a list
92             of URLs and an easy way to navigate through them.
93              
94             Note that Fixflo have a habit of updating their API to add new attributes to the
95             entities - these would normally cause the parsing of the envelope data to throw
96             an exception, but a check is in place to defend against this. If you want to see
97             warnings about those then set C on this Resource object
98             (a boolean, which defaults to false).
99              
100             =cut
101              
102             sub to_hash {
103 29     29 1 1040 my ( $self ) = @_;
104              
105 29         64 my %hash = %{ $self };
  29         350  
106              
107 29         86 delete( $hash{client} );
108 29         191 delete( $hash{warn_unknown_attributes} );
109              
110 29         212 return %hash;
111             }
112              
113             sub to_json {
114 1     1 1 4 my ( $self ) = @_;
115 1         27 return JSON->new->canonical->encode( { $self->to_hash } );
116             }
117              
118             sub get {
119 7     7 1 65 my ( $self ) = @_;
120              
121 7         206 my $data = $self->client->api_get( $self->url );
122              
123 7         111 foreach my $attr ( keys( %{ $data } ) ) {
  7         35  
124 18     18   1515 try { $self->$attr( $data->{$attr} ); }
125             catch {
126 1     1   15 my $e = $_;
127              
128 1 50 33     31 if (
129             $e =~ /Can't locate object method/
130             && $self->warn_unknown_attributes
131             ) {
132 0         0 carp( "Couldn't set $attr on @{[ ref( $self ) ]}: $e" );
  0         0  
133             }
134 18         361 };
135             }
136              
137 7         147 return $self;
138             }
139              
140             sub _parse_envelope_data {
141 24     24   2576 my ( $self,$data ) = @_;
142              
143 24 100       190 return $self if ! ref( $data );
144              
145             my $Envelope = Business::Fixflo::Envelope->new(
146             client => $self->client,
147 2         10 %{ $data }
  2         25  
148             );
149              
150 2   100     5 foreach my $attr ( keys( %{ $Envelope->Entity // {} } ) ) {
  2         16  
151 0     0   0 try { $self->$attr( $Envelope->Entity->{$attr} ); }
152             catch {
153 0     0   0 my $e = $_;
154              
155 0 0 0     0 if (
156             $e =~ /Can't locate object method/
157             && $self->warn_unknown_attributes
158             ) {
159 0         0 carp( "Couldn't set $attr on @{[ ref( $self ) ]}: $e" );
  0         0  
160             }
161 0         0 };
162             }
163              
164 2         53 return $self;
165             }
166              
167             sub _create {
168 27     27   79 my ( $self,$update,$class,$cb ) = @_;
169              
170 27 100 100     309 if ( ! $update && $self->Id ) {
    100 100        
171 6         87 Business::Fixflo::Exception->throw({
172             message => "Can't create $class when Id is already set",
173             });
174             } elsif ( $update && ! $self->Id ) {
175 5         42 Business::Fixflo::Exception->throw({
176             message => "Can't update $class if Id is not set",
177             });
178             }
179              
180 16         93 my $post_data = $cb->( $self );
181              
182 16         103 return $self->_parse_envelope_data(
183             $self->client->api_post( $class,$post_data )
184             );
185             }
186              
187             sub _paginated_items {
188 3     3   12 my ( $self,$class,$item_class,$item_class_singular ) = @_;
189              
190 3         18 my $items = $self->client->api_get(
191 3         25 "$class/@{[ $self->Id ]}/$item_class",
192             );
193              
194 3         29 my $b_ff_class = "Business::Fixflo::$item_class_singular";
195              
196             my $Paginator = Business::Fixflo::Paginator->new(
197             links => {
198             next => $items->{NextURL},
199             previous => $items->{PreviousURL},
200             },
201             client => $self->client,
202             class => 'Business::Fixflo::Issue',
203             objects => [ map { $b_ff_class->new(
204             client => $self->client,
205 9         81 %{ $_ },
  9         151  
206 3         19 ) } @{ $items->{Items} } ],
  3         8  
207             );
208              
209 3         3330 return $Paginator;
210             }
211              
212             sub update {
213 10     10 0 6500 my ( $self ) = @_;
214 10         48 return $self->create( 'update' );
215             }
216              
217             =head1 AUTHOR
218              
219             Lee Johnson - C
220              
221             This library is free software; you can redistribute it and/or modify it under
222             the same terms as Perl itself. If you would like to contribute documentation,
223             features, bug fixes, or anything else then please raise an issue / pull request:
224              
225             https://github.com/Humanstate/business-fixflo
226              
227             =cut
228              
229             1;
230              
231             # vim: ts=4:sw=4:et