summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkanat%bugzilla.org <>2009-01-23 01:57:09 +0100
committermkanat%bugzilla.org <>2009-01-23 01:57:09 +0100
commit4c70e508fc19c13e1a6274c388b7da4c31efb846 (patch)
tree7b62fb91cb5d16b1df06930a824a5680c44423cd
parent2883bee0ad4251a51a4acf48991244a605770df7 (diff)
downloadbugzilla-4c70e508fc19c13e1a6274c388b7da4c31efb846.tar.gz
bugzilla-4c70e508fc19c13e1a6274c388b7da4c31efb846.tar.xz
Bug 398281: Basic search for bugs via WebService (Bug.search)
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=dkl, a=mkanat
-rwxr-xr-xBugzilla/WebService/Bug.pm315
1 files changed, 261 insertions, 54 deletions
diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm
index 2ec52c51b..04b18fe7c 100755
--- a/Bugzilla/WebService/Bug.pm
+++ b/Bugzilla/WebService/Bug.pm
@@ -40,11 +40,16 @@ use Bugzilla::Util qw(trim);
# make sense to somebody who's not intimately familiar with the inner workings
# of Bugzilla. (These are the field names that the WebService uses.)
use constant FIELD_MAP => {
- status => 'bug_status',
- severity => 'bug_severity',
- description => 'comment',
- summary => 'short_desc',
- platform => 'rep_platform',
+ creation_time => 'creation_ts',
+ description => 'comment',
+ id => 'bug_id',
+ last_change_time => 'delta_ts',
+ platform => 'rep_platform',
+ severity => 'bug_severity',
+ status => 'bug_status',
+ summary => 'short_desc',
+ url => 'bug_file_loc',
+ whiteboard => 'status_whiteboard',
};
use constant PRODUCT_SPECIFIC_FIELDS => qw(version target_milestone component);
@@ -145,47 +150,7 @@ sub get {
my @return;
foreach my $bug_id (@$ids) {
my $bug = Bugzilla::Bug->check($bug_id);
-
- # Timetracking fields are deleted if the user doesn't belong to
- # the corresponding group.
- unless (Bugzilla->user->in_group(Bugzilla->params->{'timetrackinggroup'})) {
- delete $bug->{'estimated_time'};
- delete $bug->{'remaining_time'};
- delete $bug->{'deadline'};
- }
- # This is done in this fashion in order to produce a stable API.
- # The internals of Bugzilla::Bug are not stable enough to just
- # return them directly.
- my %item;
- $item{'creation_time'} = $self->type('dateTime', $bug->creation_ts);
- $item{'last_change_time'} = $self->type('dateTime', $bug->delta_ts);
- $item{'internals'} = $bug;
- $item{'id'} = $self->type('int', $bug->bug_id);
- $item{'summary'} = $self->type('string', $bug->short_desc);
- $item{'assigned_to'} = $self->type('string', $bug->assigned_to->login );
- $item{'resolution'} = $self->type('string', $bug->resolution);
- $item{'status'} = $self->type('string', $bug->bug_status);
- $item{'is_open'} = $self->type('boolean', $bug->status->is_open);
- $item{'severity'} = $self->type('string', $bug->bug_severity);
- $item{'priority'} = $self->type('string', $bug->priority);
- $item{'product'} = $self->type('string', $bug->product);
- $item{'component'} = $self->type('string', $bug->component);
- $item{'dupe_of'} = $self->type('int', $bug->dup_id);
-
- # if we do not delete this key, additional user info, including their
- # real name, etc, will wind up in the 'internals' hashref
- delete $item{internals}->{assigned_to_obj};
-
- if (Bugzilla->params->{'usebugaliases'}) {
- $item{'alias'} = $self->type('string', $bug->alias);
- }
- else {
- # For API reasons, we always want the value to appear, we just
- # don't want it to have a value if aliases are turned off.
- $item{'alias'} = undef;
- }
-
- push(@return, \%item);
+ push(@return, $self->_bug_to_hash($bug))
}
return { bugs => \@return };
@@ -251,21 +216,25 @@ sub get_history {
return { bugs => \@return };
}
+sub search {
+ my ($self, $params) = @_;
+ $params = _map_fields($params);
+ my $bugs = Bugzilla::Bug->match($params);
+ my $visible = Bugzilla->user->visible_bugs($bugs);
+ my @hashes = map { $self->_bug_to_hash($_) } @$visible;
+ return { bugs => \@hashes };
+}
+
sub create {
my ($self, $params) = @_;
Bugzilla->login(LOGIN_REQUIRED);
- my %field_values;
- foreach my $field (keys %$params) {
- my $field_name = FIELD_MAP->{$field} || $field;
- $field_values{$field_name} = $params->{$field};
- }
-
+ $params = _map_fields($params);
# WebService users can't set the creation date of a bug.
- delete $field_values{'creation_ts'};
+ delete $params->{'creation_ts'};
- my $bug = Bugzilla::Bug->create(\%field_values);
+ my $bug = Bugzilla::Bug->create($params);
Bugzilla::BugMail::Send($bug->bug_id, { changer => $bug->reporter->login });
@@ -403,6 +372,75 @@ sub update_see_also {
return { changes => \%changes };
}
+##############################
+# Private Helper Subroutines #
+##############################
+
+# A helper for get() and search().
+sub _bug_to_hash {
+ my ($self, $bug) = @_;
+
+ # Timetracking fields are deleted if the user doesn't belong to
+ # the corresponding group.
+ unless (Bugzilla->user->is_timetracker) {
+ delete $bug->{'estimated_time'};
+ delete $bug->{'remaining_time'};
+ delete $bug->{'deadline'};
+ }
+
+ # This is done in this fashion in order to produce a stable API.
+ # The internals of Bugzilla::Bug are not stable enough to just
+ # return them directly.
+ my %item;
+ $item{'internals'} = $bug;
+ $item{'creation_time'} = $self->type('dateTime', $bug->creation_ts);
+ $item{'last_change_time'} = $self->type('dateTime', $bug->delta_ts);
+ $item{'id'} = $self->type('int', $bug->bug_id);
+ $item{'summary'} = $self->type('string', $bug->short_desc);
+ $item{'assigned_to'} = $self->type('string', $bug->assigned_to->login);
+ $item{'resolution'} = $self->type('string', $bug->resolution);
+ $item{'status'} = $self->type('string', $bug->bug_status);
+ $item{'is_open'} = $self->type('boolean', $bug->status->is_open);
+ $item{'severity'} = $self->type('string', $bug->bug_severity);
+ $item{'priority'} = $self->type('string', $bug->priority);
+ $item{'product'} = $self->type('string', $bug->product);
+ $item{'component'} = $self->type('string', $bug->component);
+ $item{'dupe_of'} = $self->type('int', $bug->dup_id);
+
+ # if we do not delete this key, additional user info, including their
+ # real name, etc, will wind up in the 'internals' hashref
+ delete $item{internals}->{assigned_to_obj};
+
+ if (Bugzilla->params->{'usebugaliases'}) {
+ $item{'alias'} = $self->type('string', $bug->alias);
+ }
+ else {
+ # For API reasons, we always want the value to appear, we just
+ # don't want it to have a value if aliases are turned off.
+ $item{'alias'} = undef;
+ }
+
+ return \%item;
+}
+
+# Convert WebService API field names to internal DB field names.
+# Used by create() and search().
+sub _map_fields {
+ my ($params) = @_;
+
+ my %field_values;
+ foreach my $field (keys %$params) {
+ my $field_name = FIELD_MAP->{$field} || $field;
+ $field_values{$field_name} = $params->{$field};
+ }
+
+ unless (Bugzilla->user->is_timetracker) {
+ delete @field_values{qw(estimated_time remaining_time deadline)};
+ }
+
+ return \%field_values;
+}
+
1;
__END__
@@ -856,12 +894,181 @@ The same as L</get>.
=back
+
+=item C<search>
+
+B<UNSTABLE>
+
+=over
+
+=item B<Description>
+
+Allows you to search for bugs based on particular criteria.
+
+=item B<Params>
+
+Bugs are returned if they match I<exactly> the criteria you specify
+in these parameters. That is, we don't match against
+substrings--if a bug is in the "Widgets" product and you ask for bugs in
+the "Widg" product, you won't get anything.
+
+Criteria are joined in a logical AND. That is, you will be returned
+bugs that match I<all> of the criteria, not bugs that match I<any> of
+the criteria.
+
+Each parameter can be either the type it says, or an array of the types
+it says. If you pass an array, it means "Give me bugs with I<any> of
+these values." For example, if you wanted bugs that were in either
+the "Foo" or "Bar" products, you'd pass:
+
+ product => ['Foo', 'Bar']
+
+Fields below only have descriptions if it's not clear what bug field
+they match up to, or if they have some special behavior.
+
+Some Bugzillas may treat your arguments case-sensitively, depending
+on what database system they are using. Most commonly, though, Bugzilla is
+not case-sensitive with the arguments passed (because MySQL is the
+most-common database to use with Bugzilla, and MySQL is not case sensitive).
+
+=over
+
+=item C<alias>
+
+C<string> The unique alias for this bug. Note that you can search
+by alias even if the alias field is disabled in this Bugzilla, but
+it's likely that there won't be any aliases set on bugs, in that case.
+
+=item C<assigned_to>
+
+C<string> The login name of a user that a bug is assigned to.
+
+=item C<component>
+
+C<string> The name of the Component that the bug is in. Note that
+if there are multiple Compoonents with the same name, and you search
+for that name, bugs in I<all> those Components will be returned. If you
+don't want this, be sure to also specify the C<product> argument.
+
+=item C<creation_time>
+
+C<dateTime> When the bug was created.
+
+=item C<id>
+
+C<int> The numeric id of the bug.
+
+=item C<last_change_time>
+
+C<dateTime> The last time the bug was updated.
+
+=item C<op_sys>
+
+C<string> The "Operating System" field of a bug.
+
+=item C<platform>
+
+C<string> The Platform (sometimes called "Hardware") field of a bug.
+
+=item C<priority>
+
+C<string> The Priority field on a bug.
+
+=item C<product>
+
+C<string> The name of the Product that the bug is in.
+
+=item C<reporter>
+
+C<string> The login name of the user who reported the bug.
+
+=item C<resolution>
+
+C<string> The current resolution--only set if a bug is closed. You can
+find open bugs by searching for bugs with an empty resolution.
+
+=item C<severity>
+
+C<string> The Severity field on a bug.
+
+=item C<status>
+
+C<string> The current status of a bug (not including its resolution,
+if it has one, which is a separate field above).
+
+=item C<summary>
+
+C<string> The single-line summary field of a bug. (This isn't very
+useful to search on, since we don't do substring matches, only exact
+matches.)
+
+=item C<target_milestone>
+
+C<string> The Target Milestone field of a bug. Note that even if this
+Bugzilla does not have the Target Milestone field enabled, you can
+still search for bugs by Target Milestone. However, it is likely that
+in that case, most bugs will not have a Target Milestone set (it
+defaults to "---" when the field isn't enabled).
+
+=item C<qa_contact>
+
+C<string> The login name of the bug's QA Contact. Note that even if
+this Bugzilla does not have the QA Contact field enabled, you can
+still search for bugs by QA Contact (though it is likely that no bug
+will have a QA Contact set, if the field is disabled).
+
+=item C<url>
+
+C<string> The "URL" field of a bug.
+
+=item C<version>
+
+C<string> The Version field of a bug.
+
+=item C<votes>
+
+C<int> How many votes this bug has, total.
+
+=item C<whiteboard>
+
+C<string> The "Status Whiteboard" field of a bug.
+
+=back
+
+=item B<Returns>
+
+The same as L</get>.
+
+Note that you will only be returned information about bugs that you
+can see. Bugs that you can't see will be entirely excluded from the
+results. So, if you want to see private bugs, you will have to first
+log in and I<then> call this method.
+
+=item B<Errors>
+
+Currently, this function doesn't throw any special errors (other than
+the ones that all webservice functions can throw). If you specify
+an invalid value for a particular field, you just won't get any results
+for that value.
+
+=item B<History>
+
+=over
+
+=item Added in Bugzilla B<3.4>.
+
+=back
+
+=back
+
+
=back
=head2 Bug Creation and Modification
=over
+
=item C<create>
B<EXPERIMENTAL>