From 559f89582199e4ca531398a5cadd03632526d525 Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Wed, 7 Jan 2009 21:22:08 +0000 Subject: Bug 450403: Add ability to view comments via the web service (Bug.comments) Patch By Max Kanat-Alexander r=dkl, a=mkanat --- Bugzilla/WebService.pm | 62 +++++++++++++ Bugzilla/WebService/Bug.pm | 196 +++++++++++++++++++++++++++++++++++++++ Bugzilla/WebService/Constants.pm | 4 + Bugzilla/WebService/User.pm | 32 +------ 4 files changed, 266 insertions(+), 28 deletions(-) (limited to 'Bugzilla') diff --git a/Bugzilla/WebService.pm b/Bugzilla/WebService.pm index 438a66710..615abf68c 100755 --- a/Bugzilla/WebService.pm +++ b/Bugzilla/WebService.pm @@ -294,3 +294,65 @@ an error 302, there won't be an error -302. Sometimes a function will throw an error that doesn't have a specific error code. In this case, the code will be C<-32000> if it's a "fatal" error, and C<32000> if it's a "transient" error. + +=head1 COMMON PARAMETERS + +Many Webservice methods take similar arguments. Instead of re-writing +the documentation for each method, we document the parameters here, once, +and then refer back to this documentation from the individual methods +where these parameters are used. + +=head2 Limiting What Fields Are Returned + +Many WebService methods return an array of structs with various +fields in the structs. (For example, L +returns a list of C that have fields like C, C, +C, etc.) + +These parameters allow you to limit what fields are present in +the structs, to possibly improve performance or save some bandwidth. + +=over + +=item C (array) + +An array of strings, representing the (case-sensitive) names of fields. +Only the fields specified in this hash will be returned, the rest will +not be included. + +If you specify an empty array, then this function will return empty +hashes. + +Invalid field names are ignored. + +Example: + + User.get( ids => [1], include_fields => ['id', 'name'] ) + +would return something like: + + { users => [{ id => 1, name => 'user@domain.com' }] } + +=item C (array) + +An array of strings, representing the (case-sensitive) names of fields. +The fields specified will not be included in the returned hashes. + +If you specify all the fields, then this function will return empty +hashes. + +Invalid field names are ignored. + +Specifying fields here overrides C, so if you specify a +field in both, it will be excluded, not included. + +Example: + + User.get( ids => [1], exclude_fields => ['name'] ) + +would return something like: + + { users => [{ id => 1, real_name => 'John Smith' }] } + +=back + diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm index aaaf753a3..10ea1f886 100755 --- a/Bugzilla/WebService/Bug.pm +++ b/Bugzilla/WebService/Bug.pm @@ -27,6 +27,7 @@ use Bugzilla::Constants; use Bugzilla::Error; use Bugzilla::Field; use Bugzilla::WebService::Constants; +use Bugzilla::WebService::Util qw(filter); use Bugzilla::Bug; use Bugzilla::BugMail; use Bugzilla::Util qw(trim); @@ -58,6 +59,84 @@ BEGIN { *get_bugs = \&get } # Methods # ########### +sub comments { + my ($self, $params) = @_; + if (!(defined $params->{bug_ids} || defined $params->{comment_ids})) { + ThrowCodeError('params_required', + { function => 'Bug.comments', + params => ['bug_ids', 'comment_ids'] }); + } + + my $bug_ids = $params->{bug_ids} || []; + my $comment_ids = $params->{comment_ids} || []; + + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + + my %bugs; + foreach my $bug_id (@$bug_ids) { + my $bug = Bugzilla::Bug->check($bug_id); + # We want the API to always return comments in the same order. + my $comments = Bugzilla::Bug::GetComments( + $bug->id, 'oldest_to_newest'); + my @result; + foreach my $comment (@$comments) { + next if $comment->{isprivate} && !$user->is_insider; + $comment->{bug_id} = $bug->id; + push(@result, $self->_translate_comment($comment, $params)); + } + $bugs{$bug->id}{'comments'} = \@result; + } + + my %comments; + if (scalar @$comment_ids) { + my @ids = map { trim($_) } @$comment_ids; + my @sql_ids = map { $dbh->quote($_) } @ids; + my $comment_data = $dbh->selectall_arrayref( + 'SELECT comment_id AS id, bug_id, who, bug_when AS time, + isprivate, thetext AS body, type, extra_data + FROM longdescs WHERE ' . $dbh->sql_in('comment_id', \@sql_ids), + {Slice=>{}}); + + # See if we were passed any invalid comment ids. + my %got_ids = map { $_->{id} => 1 } @$comment_data; + foreach my $comment_id (@ids) { + if (!$got_ids{$comment_id}) { + ThrowUserError('comment_id_invalid', { id => $comment_id }); + } + } + + # Now make sure that we can see all the associated bugs. + my %got_bug_ids = map { $_->{bug_id} => 1 } @$comment_data; + Bugzilla::Bug->check($_) foreach (keys %got_bug_ids); + + foreach my $comment (@$comment_data) { + if ($comment->{isprivate} && !$user->is_insider) { + ThrowUserError('comment_is_private', { id => $comment->{id} }); + } + $comment->{author} = new Bugzilla::User($comment->{who}); + $comment->{body} = Bugzilla::Bug::format_comment($comment); + $comments{$comment->{id}} = + $self->_translate_comment($comment, $params); + } + } + + return { bugs => \%bugs, comments => \%comments }; +} + +# Helper for Bug.comments +sub _translate_comment { + my ($self, $comment, $filters) = @_; + return filter $filters, { + id => $self->type('int', $comment->{id}), + bug_id => $self->type('int', $comment->{bug_id}), + author => $self->type('string', $comment->{author}->login), + time => $self->type('dateTime', $comment->{'time'}), + is_private => $self->type('boolean', $comment->{isprivate}), + text => $self->type('string', $comment->{body}), + }; +} + sub get { my ($self, $params) = @_; my $ids = $params->{ids}; @@ -326,6 +405,123 @@ You specified a field that doesn't exist or isn't a drop-down field. =over + +=item C + +B + +=over + +=item B + +This allows you to get data about comments, given a list of bugs +and/or comment ids. + +=item B + +B: At least one of C or C is required. + +In addition to the parameters below, this method also accepts the +standard L and +L arguments. + +=over + +=item C + +C An array that can contain both bug IDs and bug aliases. +All of the comments (that are visible to you) will be returned for the +specified bugs. + +=item C + +C An array of integer comment_ids. These comments will be +returned individually, separate from any other comments in their +respective bugs. + +=back + +=item B + +Two items are returned: + +=over + +=item C + +This is used for bugs specified in C. This is a hash, +where the keys are the numeric ids of the bugs, and the value is +a hash with a single key, C, which is an array of comments. +(The format of comments is described below.) + +Note that any individual bug will only be returned once, so if you +specify an id multiple times in C, it will still only be +returned once. + +=item C + +Each individual comment requested in C is returned here, +in a hash where the numeric comment id is the key, and the value +is the comment. (The format of comments is described below.) + +=back + +A "comment" as described above is a hash that contains the following +keys: + +=over + +=item id + +C The globally unique ID for the comment. + +=item bug_id + +C The ID of the bug that this comment is on. + +=item text + +C The actual text of the comment. + +=item author + +C The login name of the comment's author. + +=item time + +C The time (in Bugzilla's timezone) that the comment was added. + +=item is_private + +C True if this comment is private (only visible to a certain +group called the "insidergroup"), False otherwise. + +=back + +=item B + +This method can throw all the same errors as L. In addition, +it can also throw the following errors: + +=over + +=item 110 (Comment Is Private) + +You specified the id of a private comment in the C +argument, and you are not in the "insider group" that can see +private comments. + +=item 111 (Invalid Comment ID) + +You specified an id in the C argument that is invalid--either +you specified something that wasn't a number, or there is no comment with +that id. + +=back + +=back + + =item C B diff --git a/Bugzilla/WebService/Constants.pm b/Bugzilla/WebService/Constants.pm index 593801a6f..07b51e5f1 100755 --- a/Bugzilla/WebService/Constants.pm +++ b/Bugzilla/WebService/Constants.pm @@ -51,6 +51,7 @@ use constant WS_ERROR_CODE => { # Generic Bugzilla::Object errors are 50-99. object_not_specified => 50, param_required => 50, + params_required => 50, object_does_not_exist => 51, # Bug errors usually occupy the 100-200 range. improper_bug_id_field_value => 100, @@ -79,6 +80,9 @@ use constant WS_ERROR_CODE => { invalid_field_name => 108, # Not authorized to edit the bug product_edit_denied => 109, + # Comment-related errors + comment_is_private => 110, + comment_id_invalid => 111, # Authentication errors are usually 300-400. invalid_username_or_password => 300, diff --git a/Bugzilla/WebService/User.pm b/Bugzilla/WebService/User.pm index 24b9be709..6283f55a1 100755 --- a/Bugzilla/WebService/User.pm +++ b/Bugzilla/WebService/User.pm @@ -451,6 +451,10 @@ B: At least one of C, C, or C must be specified. B: Users will not be returned more than once, so even if a user is matched by more than one argument, only one user will be returned. +In addition to the parameters below, this method also accepts the +standard L and +L arguments. + =over =item C (array) @@ -482,34 +486,6 @@ if they try. (This is to make it harder for spammers to harvest email addresses from Bugzilla, and also to enforce the user visibility restrictions that are implemented on some Bugzillas.) -=item C (array) - -An array of strings, representing the names of keys in the hashes -this function returns. Only the fields specified in this hash will be -returned, the rest will not be included. - -Essentially, this is a way to make the return value smaller, for performance -or bandwidth reasons. - -If you specify an empty array, then this function will return empty hashes. - -Invalid field names are ignored. - -=item C (array) - -An array of strings, representing the names of keys in the hashes this -function returns. The fields specified will not be excluded from the -returned hashes. - -Essentially, this is a way to exclude certain fields from the returned -hashes, for performance or bandwidth reasons. - -If you specify all the fields, then this function will return empty hashes. - -Invalid field names are ignored. - -This overrides C. - =back =item B -- cgit v1.2.3-24-g4f1b