File Coverage

blib/lib/Net/Lighthouse/Project/Ticket.pm
Criterion Covered Total %
statement 70 111 63.0
branch 17 32 53.1
condition n/a
subroutine 9 12 75.0
pod 7 7 100.0
total 103 162 63.5


line stmt bran cond sub pod time code
1             package Net::Lighthouse::Project::Ticket;
2 11     11   62 use Any::Moose;
  11         21  
  11         115  
3 11     11   6621 use Params::Validate ':all';
  11         24  
  11         2393  
4 11     11   64 use Net::Lighthouse::Util;
  11         19  
  11         1934  
5             extends 'Net::Lighthouse::Base';
6             # read only attr
7             has [qw/created_at updated_at milestone_due_on/] => (
8             isa => 'Maybe[DateTime]',
9             is => 'ro',
10             );
11              
12             has [qw/number priority user_id project_id creator_id attachments_count/] => (
13             isa => 'Maybe[Int]',
14             is => 'ro',
15             );
16              
17             has [qw/closed /] => (
18             isa => 'Bool',
19             is => 'ro',
20             );
21              
22             has [
23             'raw_data', 'user_name',
24             'permalink', 'url',
25             'latest_body', 'creator_name',
26             'assigned_user_name', 'milestone_title',
27             ] => (
28             isa => 'Maybe[Str]',
29             is => 'ro',
30             );
31              
32             has 'attachments' => (
33             isa => 'ArrayRef[Net::Lighthouse::Project::Ticket::Attachment]',
34             is => 'ro',
35             auto_deref => 1,
36             );
37              
38             has 'versions' => (
39             isa => 'ArrayRef[Net::Lighthouse::Project::Ticket::Version]',
40             is => 'ro',
41             auto_deref => 1,
42             );
43              
44             # read&write attr
45             has [qw/assigned_user_id milestone_id/] => (
46             isa => 'Maybe[Int]',
47             is => 'rw',
48             );
49              
50             has [qw/title state tag/] => (
51             isa => 'Maybe[Str]',
52             is => 'rw',
53             );
54              
55 11     11   62 no Any::Moose;
  11         22  
  11         65  
56             __PACKAGE__->meta->make_immutable;
57              
58             sub load {
59 1     1 1 20306 my $self = shift;
60 1         43 validate_pos( @_, { type => SCALAR, regex => qr/^\d+$/ } );
61 1         28 my $number = shift;
62 1         28 my $ua = $self->ua;
63 1         10 my $url =
64             $self->base_url
65             . '/projects/'
66             . $self->project_id . '/tickets/'
67             . $number . '.xml';
68 1         10 my $res = $ua->get( $url );
69 1 50       67 if ( $res->is_success ) {
70 1         62 $self->load_from_xml( $res->content );
71             }
72             else {
73 0         0 die "try to get $url failed: "
74             . $res->status_line . "\n"
75             . $res->content;
76             }
77             }
78              
79             sub load_from_xml {
80 7     7 1 217 my $self = shift;
81 7         22 my $ref = $self->_translate_from_xml( shift );
82              
83             # dirty hack: some attrs are read-only, and Mouse doesn't support
84             # writer => '...'
85 7         232 for my $k ( keys %$ref ) {
86 153         1303 $self->{$k} = $ref->{$k};
87             }
88 7         47 return $self;
89             }
90              
91             sub _translate_from_xml {
92 8     8   195 my $self = shift;
93 8         46 my $ref = Net::Lighthouse::Util->translate_from_xml( shift );
94 8         227 for my $k ( keys %$ref ) {
95 172 100       1069 if ( $k eq 'versions' ) {
    100          
96 1         4 my $versions = $ref->{versions}{version};
97 1 50       5 $versions = [ $versions ] unless ref $versions eq 'ARRAY';
98 1         800 require Net::Lighthouse::Project::Ticket::Version;
99 1         11 $ref->{versions} = [
100             map {
101 1         4 my $v = Net::Lighthouse::Project::Ticket::Version->new;
102 1         147 $v->load_from_xml($_)
103             } @$versions
104             ];
105             }
106             elsif ( $k eq 'attachments' ) {
107 1         3 my @attachments;
108 1         3 for ( keys %{$ref->{attachments}} ) {
  1         6  
109 3         10 my $att = $ref->{attachments}{$_};
110 3 100       20 next unless ref $att;
111 2 50       10 if ( ref $att eq 'ARRAY' ) {
112 0         0 push @attachments, @{$att};
  0         0  
113             }
114             else {
115 2         7 push @attachments, $att;
116             }
117             }
118 1 50       5 next unless @attachments;
119              
120 1         1136 require Net::Lighthouse::Project::Ticket::Attachment;
121 2         11 $ref->{attachments} = [
122             map {
123 1         6 my $v =
124             Net::Lighthouse::Project::Ticket::Attachment->new(
125             ua => $self->ua );
126 2         221 $v->load_from_xml($_)
127             } @attachments
128             ];
129             }
130             }
131 8         216 return $ref;
132             }
133              
134             sub create {
135 0     0 1 0 my $self = shift;
136 0         0 validate(
137             @_,
138             {
139             title => { type => SCALAR },
140             body => { type => SCALAR },
141             state => { optional => 1, type => SCALAR },
142             assigned_user_id => {
143             optional => 1,
144             type => SCALAR | UNDEF,
145             regex => qr/^(\d+|)$/,
146             },
147             milestone_id => {
148             optional => 1,
149             type => SCALAR | UNDEF,
150             regex => qr/^(\d+|)$/,
151             },
152             tag => { optional => 1, type => SCALAR },
153             }
154             );
155 0         0 my %args = @_;
156              
157 0         0 my $xml =
158             Net::Lighthouse::Util->translate_to_xml( \%args, root => 'ticket', );
159              
160 0         0 my $ua = $self->ua;
161              
162 0         0 my $url = $self->base_url . '/projects/' . $self->project_id . '/tickets.xml';
163              
164 0         0 my $request = HTTP::Request->new( 'POST', $url, undef, $xml );
165 0         0 my $res = $ua->request( $request );
166 0 0       0 if ( $res->is_success ) {
167 0         0 $self->load_from_xml( $res->content );
168 0         0 return 1;
169             }
170             else {
171 0         0 die "try to POST $url failed: "
172             . $res->status_line . "\n"
173             . $res->content;
174             }
175             }
176              
177             sub update {
178 0     0 1 0 my $self = shift;
179 0         0 validate(
180             @_,
181             {
182             title => { optional => 1, type => SCALAR },
183             body => { optional => 1, type => SCALAR },
184             state => { optional => 1, type => SCALAR },
185             assigned_user_id => {
186             optional => 1,
187             type => SCALAR | UNDEF,
188             regex => qr/^(\d+|)$/,
189             },
190             milestone_id => {
191             optional => 1,
192             type => SCALAR | UNDEF,
193             regex => qr/^(\d+|)$/,
194             },
195             tag => { optional => 1, type => SCALAR },
196             }
197             );
198 0         0 my %args = (
199             (
200 0         0 map { $_ => $self->$_ }
201             qw/title body state assigned_user_id milestone_id tag/
202             ),
203             @_
204             );
205              
206 0         0 my $xml =
207             Net::Lighthouse::Util->translate_to_xml( \%args, root => 'ticket', );
208              
209 0         0 my $ua = $self->ua;
210 0         0 my $url =
211             $self->base_url
212             . '/projects/'
213             . $self->project_id . '/tickets/'
214             . $self->number . '.xml';
215              
216 0         0 my $request = HTTP::Request->new( 'PUT', $url, undef, $xml );
217 0         0 my $res = $ua->request( $request );
218 0 0       0 if ( $res->is_success ) {
219 0         0 $self->load( $self->number ); # let's reload
220 0         0 return 1;
221             }
222             else {
223 0         0 die "try to PUT $url failed: "
224             . $res->status_line . "\n"
225             . $res->content;
226             }
227             }
228              
229             sub delete {
230 0     0 1 0 my $self = shift;
231 0         0 my $ua = $self->ua;
232 0         0 my $url =
233             $self->base_url
234             . '/projects/'
235             . $self->project_id . '/tickets/'
236             . $self->number . '.xml';
237              
238 0         0 my $request = HTTP::Request->new( 'DELETE', $url );
239 0         0 my $res = $ua->request( $request );
240 0 0       0 if ( $res->is_success ) {
241 0         0 return 1;
242             }
243             else {
244 0         0 die "try to DELETE $url failed: "
245             . $res->status_line . "\n"
246             . $res->content;
247             }
248             }
249              
250             sub list {
251 3     3 1 20650 my $self = shift;
252 3         70 validate(
253             @_,
254             {
255             query => { optional => 1, type => SCALAR },
256             page => { optional => 1, type => SCALAR, regex => qr/^\d+$/ },
257             }
258             );
259 3         17 my %args = @_;
260              
261 3         23 my $url =
262             $self->base_url . '/projects/' . $self->project_id . '/tickets.xml?';
263 3 50       14 if ( $args{query} ) {
264 0         0 require URI::Escape;
265 0         0 $url .= 'q=' . URI::Escape::uri_escape( $args{query} ) . '&';
266             }
267 3 50       10 if ( $args{page} ) {
268 0         0 $url .= 'page=' . uri_escape( $args{page} );
269             }
270              
271 3         14 my $ua = $self->ua;
272 3         16 my $res = $ua->get($url);
273 3 50       131 if ( $res->is_success ) {
274 3         155 my $ts = Net::Lighthouse::Util->read_xml( $res->content )->{tickets}{ticket};
275 18         181 my @list = map {
276 3 50       14762 my $t = Net::Lighthouse::Project::Ticket->new(
277 18         69 map { $_ => $self->$_ }
278 6         13 grep { $self->$_ } qw/account auth project_id/
279             );
280 6         30 $t->load_from_xml($_);
281             } ref $ts eq 'ARRAY' ? @$ts : $ts;
282 3 100       485 return wantarray ? @list : \@list;
283             }
284             else {
285 0         0 die "try to get $url failed: "
286             . $res->status_line . "\n"
287             . $res->content;
288             }
289              
290             }
291              
292             sub initial_state {
293 1     1 1 3 my $self = shift;
294 1         5 my $ua = $self->ua;
295 1         4 my $url =
296             $self->base_url . '/projects/' . $self->project_id . '/tickets/new.xml';
297 1         6 my $res = $ua->get( $url );
298 1 50       45 if ( $res->is_success ) {
299 1         43 return $self->_translate_from_xml( $res->content );
300             }
301             else {
302 0           die "try to get $url failed: "
303             . $res->status_line . "\n"
304             . $res->content;
305             }
306             }
307              
308             1;
309              
310             __END__