File Coverage

blib/lib/WebService/ReviewBoard/ReviewRequest.pm
Criterion Covered Total %
statement 15 105 14.2
branch 0 10 0.0
condition 0 3 0.0
subroutine 5 29 17.2
pod 20 22 90.9
total 40 169 23.6


line stmt bran cond sub pod time code
1             package WebService::ReviewBoard::ReviewRequest;
2              
3 5     5   134200 use strict;
  5         14  
  5         261  
4 5     5   30 use warnings;
  5         10  
  5         308  
5              
6 5     5   31 use base 'WebService::ReviewBoard';
  5         9  
  5         2051  
7              
8 5     5   39 use Data::Dumper;
  5         11  
  5         338  
9 5     5   27 use Log::Log4perl qw(:easy);
  5         19  
  5         53  
10              
11             # this module returns review object as string
12             sub as_string {
13 0     0 1   my $self = shift;
14              
15             return
16 0           "[REVIEW REQUEST "
17             . $self->get_id() . '] '
18             . $self->get_summary() . "\n"
19             . " Description: "
20             . $self->get_description() . "\n"
21             . " Reviewers: "
22 0           . join( ", ", @{ $self->get_reviewers() } ) . "\n"
23             . " Bugs: "
24 0           . join( ", ", @{ $self->get_bugs() } ) . "\n"
25             . " Groups: "
26 0           . join( ", ", @{ $self->get_groups() } ) . "\n";
27             }
28              
29             sub create {
30 0     0 1   my $self = shift;
31 0           my %args = @_;
32              
33 0           my $json = $self->api_post( '/api/json/reviewrequests/new/', [%args] );
34 0 0         if ( !$json->{review_request} ) {
35 0           LOGDIE "create couldn't determine ID from this JSON that it got back from the server: " . Dumper $json;
36             }
37              
38 0           $self->{rr} = $json->{review_request};
39              
40 0           return $self;
41             }
42              
43             sub fetch {
44 0     0 1   my $self = shift;
45 0           my $id = shift;
46              
47 0           my $json = $self->api_get( '/api/json/reviewrequests/' . $id );
48 0           $self->{rr} = $json->{review_request};
49              
50 0           return $self;
51             }
52              
53             sub fetch_all_from_user {
54 0     0 1   my $self = shift;
55 0           my $from_user = shift;
56              
57 0           my $json = $self->api_get( '/api/json/reviewrequests/from/user/' . $from_user );
58              
59 0           my @rrs;
60 0           foreach my $request ( @{ $json->{review_requests} } ) {
  0            
61 0           my $rr = $self->new( $self->get_review_board_url() );
62 0           $rr->{rr} = $request;
63 0           push @rrs, $rr;
64             }
65              
66 0           return @rrs;
67              
68             }
69              
70             # this method makes POST call to reviewboard and performs required action
71             sub reviewrequest_api_post {
72 0     0 1   my $self = shift;
73 0           my $action = shift;
74              
75 0           return $self->api_post( "/api/json/reviewrequests/" . $self->get_id() . "/$action/", @_ );
76             }
77              
78 0     0 1   sub get_id { return shift->_get_field('id'); }
79 0     0 1   sub get_description { return shift->_get_field('description'); }
80 0     0 1   sub get_summary { return shift->_get_field('summary'); }
81 0     0 1   sub get_bugs { return shift->_get_field('bugs_closed'); }
82              
83             sub get_reviewers {
84 0     0 1   my $self = shift;
85 0           return [ map { $_->{username} } @{ $self->_get_field('target_people') } ];
  0            
  0            
86             }
87              
88             sub get_groups {
89 0     0 1   my $self = shift;
90 0           return [ map { $_->{name} } @{ $self->_get_field('target_groups') } ];
  0            
  0            
91             }
92              
93             sub get_reviews {
94 0     0 0   my $self = shift;
95              
96 0           my $r = $self->reviewrequest_api_post('reviews');
97 0 0         if ( ref( $r->{reviews} ) ne "ARRAY" ) {
98 0           WARN "api post to fetch reviews didn't return { 'reviews' : [] } as expected";
99             }
100              
101 0           return $r->{reviews};
102             }
103              
104             sub get_ship_it_count {
105 0     0 0   my $self = shift;
106              
107 0           my $ship_it_count = 0;
108 0           my $reviews = $self->get_reviews();
109              
110 0           foreach my $review ( @{$reviews} ) {
  0            
111 0 0         $ship_it_count++ if $review->{ship_it};
112             }
113              
114 0           return $ship_it_count;
115             }
116              
117             sub _get_field {
118 0     0     my $self = shift;
119 0           my $field = shift;
120              
121 0 0 0       if ( !$self->{rr} || !$self->{rr}->{$field} ) {
122 0           LOGDIE "requested $field, but $field isn't set. Maybe you need to call fetch first?";
123             }
124              
125 0           return $self->{rr}->{$field};
126             }
127              
128 0     0 1   sub set_description { return shift->_set_field( 'description', @_ ); }
129 0     0 1   sub set_summary { return shift->_set_field( 'summary', @_ ); }
130              
131             sub set_bugs {
132 0     0 1   my $self = shift;
133 0           my @bugs = @_;
134              
135 0           return $self->_set_field( 'bugs_closed', join( ',', @bugs ) );
136             }
137              
138             sub set_reviewers {
139 0     0 1   my $self = shift;
140 0           my @reviewers = @_;
141              
142 0           return $self->_set_field( "target_people", join( ',', @reviewers ) );
143             }
144              
145             # sets groups for given review object
146             sub set_groups {
147 0     0 1   my $self = shift;
148 0           my @groups = @_;
149 0           return $self->_set_field( 'target_groups', join( ',', @groups ) );
150             }
151              
152             sub _set_field {
153 0     0     my $self = shift;
154 0           my $field = shift;
155 0           my $value = shift;
156              
157             # update the cache
158 0           $self->{rr}->{$field} = $value;
159              
160             # send it to the server
161 0           return $self->reviewrequest_api_post( "draft/set/$field", [ value => $value, ] );
162             }
163              
164             # discards given review object
165             sub discard_review_request {
166 0     0 1   my $self = shift;
167 0           return $self->reviewrequest_api_post( "close/discarded" );
168             }
169              
170             # set status as submit for given review object
171             sub submit_review_request {
172 0     0 1   my $self = shift;
173 0           return $self->reviewrequest_api_post( "close/submitted" );
174             }
175              
176             sub publish {
177 0     0 1   my $self = shift;
178              
179 0           return $self->api_post( "/api/json/reviewrequests/" . $self->get_id() . "/publish/" );
180             }
181              
182             sub add_diff {
183 0     0 1   my $self = shift;
184 0           my $file = shift;
185 0           my $basedir = shift;
186              
187 0           my $args = [ path => [$file] ];
188              
189             # base dir is used only for some SCMs (like SVN) (I think)
190 0 0         if ($basedir) {
191 0           push @{$args}, ( basedir => $basedir );
  0            
192             }
193              
194 0           $self->reviewrequest_api_post( 'diff/new', Content_Type => 'form-data', Content => $args );
195              
196 0           return 1;
197             }
198              
199             1;
200              
201             __END__
202              
203             WebService::ReviewBoard::ReviewRequest - An object that represents a review on the review board system
204              
205             =head1 SYNOPSIS
206              
207             use WebService::ReviewBoard::ReviewRequest;
208              
209             my $rb = WebService::ReviewBoard::ReviewRequest->new( 'http://demo.review-board.org' );
210             $rb->login( 'username', 'password' );
211              
212             $rb->create( repository_id => 1 );
213             $rb->set_bugs( 1728212, 1723823 );
214             $rb->set_reviewers( qw( jdagnall gno ) );
215             $rb->set_summary( "this is the summary" );
216             $rb->set_description( "this is the description" );
217             $rb->set_groups('reviewboard');
218             $rb->add_diff( '/tmp/patch' );
219             $rb->publish();
220            
221             # get all the reviews that the user jaybuff created:
222             foreach my $review_request ( $rr->fetch_all_from_user( 'jaybuff' ) ) {
223             print "[REVIEW REQUEST" . $review_request->get_id() . "] " . $review_request->get_summary() . "\n";
224             }
225              
226             # get review request 123
227             $rr->fetch( 123 );
228              
229             # return the number of ship its
230             print "Number of ship its for review request #" . $rr->get_id() . ": " . $rr->get_ship_it_count() . "\n";
231              
232             # set status as submitted
233             $rr->submit_review_request();
234              
235             # discard review request
236             $rr->discard_review_request();
237            
238             =head1 DESCRIPTION
239              
240             =head1 INTERFACE
241              
242             =over
243              
244             =item C<< create( %args ) >>
245              
246             C<<%args>> is passed directly to the HTTP UserAgent when it does the request.
247              
248             C<<%args>> must contain which repository to use. Using one of these (from the ReviewBoard API documentation):
249              
250             * repository_path: The repository to create the review request against. If not specified, the DEFAULT_REPOSITORY_PATH setting will be used. If both this and repository_id are set, repository_path's value takes precedence.
251             * repository_id: The ID of the repository to create the review request against.
252              
253             Example:
254              
255             my $rr = WebService::ReviewBoard::ReviewRequest->new( 'http://demo.review-board.org' );
256             $rr->login( 'username', 'password' );
257             $rr->create( repository_id => 1 );
258              
259             =item C<< fetch( $id ) >>
260              
261             Fetch a review request.
262              
263             =item C<< fetch_all_from_user( $user ) >>
264              
265             Returns an array of WebService::ReviewBoard::ReviewRequest objects
266              
267             =item C<< get_id() >>
268              
269             Returns the id of this review request
270              
271             =item C<< get_bugs() >>
272              
273             Returns an array.
274              
275             =item C<< get_reviewers() >>
276              
277             Returns an array.
278              
279             =item C<< get_summary() >>
280              
281             =item C<< get_description() >>
282              
283             =item C<< get_groups() >>
284              
285             =item C<< set_groups() >>
286              
287             =item C<< set_bugs( @bug_ids ) >>
288              
289             =item C<< set_reviewers( @review_board_users ) >>
290              
291             =item C<< set_summary( $summary ) >>
292              
293             =item C<< set_description( $description ) >>
294              
295             =item C<< add_diff( $diff_file ) >>
296              
297             C<< $diff_file >> should be a file that contains the diff that you want to be reviewed.
298              
299             =item C<< publish( ) >>
300              
301             Mark the review request as ready to be reviewed. This will send out notification emails if review board
302             is configured to do that.
303              
304             =item C<< discard_review_request() >>
305             Mark the review request as discarded. This will delete review request from review board.
306              
307             =item C<< submit_review_request() >>
308             Mark the review request as submitted.
309              
310             =item C<< as_string() >>
311              
312             returns a string that is a representation of the review request
313              
314             =item C<< reviewrequest_api_post() >>
315              
316             makes POST call to reviewboard and performs required action.
317              
318             =back
319              
320             =head1 DIAGNOSTICS
321              
322             =over
323              
324             =item C<< "create couldn't determine ID from this JSON that it got back from the server: %s" >>
325             =item C<< "new() missing review_board arg (WebService::ReviewBoard object)" >>
326             =item C<< "requested id, but id isn't set" >>
327             =item C<< "fetch() must get either from_user or id as an argument" >>
328             =item C<< "no review requests matching your critera were found" >>
329             =item C<< "requested $field, but $field isn't set" >>
330              
331             =back
332              
333             =head1 CONFIGURATION AND ENVIRONMENT
334              
335             C<< WebService::ReviewBoard::ReviewBoard >> requires no configuration files or environment variables.
336              
337             =head1 DEPENDENCIES
338              
339             C<< WebService::ReviewBoard >>
340              
341             =head1 INCOMPATIBILITIES
342              
343             None reported.
344              
345             =head1 BUGS AND LIMITATIONS
346              
347             No bugs have been reported.
348              
349             Please report any bugs or feature requests to
350             C<bug-webservice-reviewboard@rt.cpan.org>, or through the web interface at
351             L<http://rt.cpan.org>.
352              
353             =head1 AUTHOR
354              
355             Jay Buffington C<< <jaybuffington@gmail.com> >>
356              
357             =head1 LICENCE AND COPYRIGHT
358              
359             Copyright (c) 2008, Jay Buffington C<< <jaybuffington@gmail.com> >>. All rights reserved.
360              
361             This module is free software; you can redistribute it and/or
362             modify it under the same terms as Perl itself. See L<perlartistic>.
363              
364             =head1 DISCLAIMER OF WARRANTY
365              
366             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
367             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
368             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
369             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
370             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
371             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
372             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
373             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
374             NECESSARY SERVICING, REPAIR, OR CORRECTION.
375              
376             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
377             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
378             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
379             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
380             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
381             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
382             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
383             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
384             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
385             SUCH DAMAGES.