File Coverage

lib/WebService/Shippo/Object.pm
Criterion Covered Total %
statement 34 98 34.6
branch 0 32 0.0
condition 0 18 0.0
subroutine 12 24 50.0
pod 0 10 0.0
total 46 182 25.2


line stmt bran cond sub pod time code
1 7     7   34 use strict;
  7         11  
  7         166  
2 7     7   32 use warnings;
  7         13  
  7         174  
3 7     7   5030 use MRO::Compat 'c3';
  7         370194  
  7         262  
4              
5             package WebService::Shippo::Object;
6 7     7   53 use Carp ( 'croak' );
  7         15  
  7         381  
7 7     7   7223 use JSON::XS ();
  7         791090  
  7         316  
8 7     7   60 use Params::Callbacks ( 'callbacks' );
  7         19  
  7         464  
9 7     7   44 use Scalar::Util ( 'blessed', 'reftype' );
  7         15  
  7         402  
10 7     7   43 use Sub::Util ( 'set_subname' );
  7         14  
  7         353  
11 7     7   38 use overload ( fallback => 1, '""' => 'to_string' );
  7         15  
  7         86  
12              
13             our $AUTOLOAD;
14              
15             sub class
16             {
17 0     0 0   my ( $invocant ) = @_;
18 0   0       return ref( $invocant ) || $invocant;
19             }
20              
21             sub new
22             {
23 0     0 0   my ( $invocant, $id ) = @_;
24 0           my $self = bless {}, $invocant->class;
25             $id = $id->{object_id}
26 0 0 0       if ref( $id ) && reftype( $id ) eq 'HASH';
27 0 0         $self->{object_id} = $id
28             if $id;
29 0           return $self;
30             }
31              
32             {
33             my $json = JSON::XS->new->utf8->convert_blessed->allow_blessed;
34              
35             sub construct_from
36             {
37 0     0 0   my ( $callbacks, $invocant, $response ) = &callbacks;
38 0           my $ref_type = ref( $response );
39 0 0         return $ref_type
40             unless defined $ref_type;
41 0 0         if ( $ref_type eq 'HASH' ) {
42 0           my $invocant = $invocant->new( $response->{object_id} );
43 0           $invocant->refresh_from( $response );
44 0 0 0       if ( exists( $invocant->{count} )
45             && exists( $invocant->{results} ) )
46             {
47 0           my $item_class = $invocant->item_class;
48             $invocant->{results}
49 0           = [ map { $callbacks->smart_transform( bless( $_, $item_class ) ) }
50 0           @{ $invocant->{results} } ];
  0            
51 0           return bless( $invocant, $invocant->collection_class );
52             }
53             else {
54 0           return $callbacks->smart_transform( $invocant );
55             }
56             }
57             else {
58 0 0         croak $response->status_line
59             unless $response->is_success;
60 0           my $content = $response->decoded_content;
61 0           my $hash = $json->decode( $content );
62 0           return $invocant->construct_from( $hash, $callbacks );
63             }
64             }
65             }
66              
67             sub refresh_from
68             {
69 0     0 0   my ( $invocant, $hash ) = @_;
70 0           @{$invocant}{ keys %$hash } = values %$hash;
  0            
71 0           return $invocant;
72             }
73              
74             sub refresh
75             {
76 0     0 0   my ( $invocant ) = @_;
77 0           my $url = $invocant->url( $invocant->{object_id} );
78 0           my $response = Shippo::Request->get( $url );
79 0           my $update = $invocant->construct_from( $response );
80 0           return $invocant->refresh_from( $update );
81             }
82              
83             sub is_same_object
84             {
85 0     0 0   my ( $invocant, $object_id ) = @_;
86             return
87 0 0         unless defined $object_id;
88             return
89 0 0         unless blessed( $invocant );
90             return
91 0 0         unless reftype( $invocant ) eq 'HASH';
92             return
93 0 0         unless exists $invocant->{object_id};
94 0           return $invocant->{object_id} eq $object_id;
95             }
96              
97             {
98             my $json = JSON::XS->new->utf8->canonical->convert_blessed->allow_blessed;
99             my $value = 0;
100              
101             sub pretty
102             {
103 0     0 0   my ( $class, $new_value ) = @_;
104 0 0         return $value unless @_ > 1;
105 0           $value = $new_value;
106 0           return $class;
107             }
108              
109             # Note to non-Perl hackers:
110             # Not having to unpack "@_" array gives slight speed boost, since it
111             # is possible that we might be creating many JSON strings in rapid
112             # succession. That weird looking "$_[0]" in the "TO_JSON", "to_json",
113             # and "to_string" methods is the first element of the "@_" array, i.e.
114             # the first argument passed to the method (the object itself).
115             #
116             # Required by JSON::XS because we use the convert_blessed encoding
117             # modifier to allow blessed references (aka Perl object instances)
118             # to be serialized. Returns a scalar value that can be serialized
119             # as JSON (essentially an unblessed shallow copy of the original
120             # object).
121             #
122             sub TO_JSON
123             {
124 0     0 0   return { %{ $_[0] } };
  0            
125             }
126              
127             # Serializes the object to a JSON string.
128             sub to_json
129             {
130 0     0 0   my ( $data, $pretty ) = @_;
131 0   0       $json->pretty( $pretty || pretty );
132 0           return $json->encode( $data );
133             }
134             }
135              
136             {
137             my $json = JSON::XS->new->utf8->canonical->convert_blessed->allow_blessed->pretty(1);
138              
139             sub to_string
140             {
141 0     0 0   return $json->encode( $_[0] );
142             }
143             }
144              
145             # Just in time creation of mutators for orphaned method calls, to facilitate
146             # access to object attributes of the same name.
147             sub AUTOLOAD
148             {
149 0     0     my ( $invocant, @args ) = @_;
150 0   0       my $class = ref( $invocant ) || $invocant;
151 0           ( my $method = $AUTOLOAD ) =~ s{^.*\::}{};
152             return
153 0 0         if $method eq 'DESTROY';
154 7     7   7075 no strict 'refs';
  7         17  
  7         1542  
155 0           my $sym = "$class\::$method";
156             *$sym = set_subname(
157             $sym => sub {
158 0     0     my ( $invocant ) = @_;
159             return ''
160 0 0         unless defined $invocant->{$method};
161 0 0 0       if ( wantarray && ref( $invocant->{$method} ) ) {
162 0           return %{ $invocant->{$method} }
163 0 0         if reftype( $invocant->{$method} ) eq 'HASH';
164 0           return @{ $invocant->{$method} }
165 0 0         if reftype( $invocant->{$method} ) eq 'ARRAY';
166             }
167 0           return $invocant->{$method};
168             }
169 0           );
170 0           goto &$sym;
171             }
172              
173             BEGIN {
174 7     7   39 no warnings 'once';
  7         15  
  7         310  
175 7     7   267 *Shippo::Object:: = *WebService::Shippo::Object::;
176             }
177              
178             1;