834 lines
22 KiB
Perl
834 lines
22 KiB
Perl
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
|
#
|
||
|
# This Source Code Form is "Incompatible With Secondary Licenses", as
|
||
|
# defined by the Mozilla Public License, v. 2.0.
|
||
|
|
||
|
package Bugzilla::WebService::FlagType;
|
||
|
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
|
||
|
use base qw(Bugzilla::WebService);
|
||
|
use Bugzilla::Component;
|
||
|
use Bugzilla::Constants;
|
||
|
use Bugzilla::Error;
|
||
|
use Bugzilla::FlagType;
|
||
|
use Bugzilla::Product;
|
||
|
use Bugzilla::Util qw(trim);
|
||
|
|
||
|
use List::MoreUtils qw(uniq);
|
||
|
|
||
|
use constant PUBLIC_METHODS => qw(
|
||
|
create
|
||
|
get
|
||
|
update
|
||
|
);
|
||
|
|
||
|
sub get {
|
||
|
my ($self, $params) = @_;
|
||
|
my $dbh = Bugzilla->switch_to_shadow_db();
|
||
|
my $user = Bugzilla->user;
|
||
|
|
||
|
defined $params->{product}
|
||
|
|| ThrowCodeError('param_required',
|
||
|
{ function => 'Bug.flag_types',
|
||
|
param => 'product' });
|
||
|
|
||
|
my $product = delete $params->{product};
|
||
|
my $component = delete $params->{component};
|
||
|
|
||
|
$product = Bugzilla::Product->check({ name => $product, cache => 1 });
|
||
|
$component = Bugzilla::Component->check(
|
||
|
{ name => $component, product => $product, cache => 1 }) if $component;
|
||
|
|
||
|
my $flag_params = { product_id => $product->id };
|
||
|
$flag_params->{component_id} = $component->id if $component;
|
||
|
my $matched_flag_types = Bugzilla::FlagType::match($flag_params);
|
||
|
|
||
|
my $flag_types = { bug => [], attachment => [] };
|
||
|
foreach my $flag_type (@$matched_flag_types) {
|
||
|
push(@{ $flag_types->{bug} }, $self->_flagtype_to_hash($flag_type, $product))
|
||
|
if $flag_type->target_type eq 'bug';
|
||
|
push(@{ $flag_types->{attachment} }, $self->_flagtype_to_hash($flag_type, $product))
|
||
|
if $flag_type->target_type eq 'attachment';
|
||
|
}
|
||
|
|
||
|
return $flag_types;
|
||
|
}
|
||
|
|
||
|
sub create {
|
||
|
my ($self, $params) = @_;
|
||
|
|
||
|
my $dbh = Bugzilla->dbh;
|
||
|
my $user = Bugzilla->user;
|
||
|
|
||
|
Bugzilla->user->in_group('editcomponents')
|
||
|
|| scalar(@{$user->get_products_by_permission('editcomponents')})
|
||
|
|| ThrowUserError("auth_failure", { group => "editcomponents",
|
||
|
action => "add",
|
||
|
object => "flagtypes" });
|
||
|
|
||
|
$params->{name} || ThrowCodeError('param_required', { param => 'name' });
|
||
|
$params->{description} || ThrowCodeError('param_required', { param => 'description' });
|
||
|
|
||
|
my %args = (
|
||
|
sortkey => 1,
|
||
|
name => undef,
|
||
|
inclusions => ['0:0'], # Default to __ALL__:__ALL__
|
||
|
cc_list => '',
|
||
|
description => undef,
|
||
|
is_requestable => 'on',
|
||
|
exclusions => [],
|
||
|
is_multiplicable => 'on',
|
||
|
request_group => '',
|
||
|
is_active => 'on',
|
||
|
is_specifically_requestable => 'on',
|
||
|
target_type => 'bug',
|
||
|
grant_group => '',
|
||
|
);
|
||
|
|
||
|
foreach my $key (keys %args) {
|
||
|
$args{$key} = $params->{$key} if defined($params->{$key});
|
||
|
}
|
||
|
|
||
|
$args{name} = trim($params->{name});
|
||
|
$args{description} = trim($params->{description});
|
||
|
|
||
|
# Is specifically requestable is actually is_requesteeable
|
||
|
if (exists $args{is_specifically_requestable}) {
|
||
|
$args{is_requesteeble} = delete $args{is_specifically_requestable};
|
||
|
}
|
||
|
|
||
|
# Default is on for the tickbox flags.
|
||
|
# If the user has set them to 'off' then undefine them so the flags are not ticked
|
||
|
foreach my $arg_name (qw(is_requestable is_multiplicable is_active is_requesteeble)) {
|
||
|
if (defined($args{$arg_name}) && ($args{$arg_name} eq '0')) {
|
||
|
$args{$arg_name} = undef;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Process group inclusions and exclusions
|
||
|
$args{inclusions} = _process_lists($params->{inclusions}) if defined $params->{inclusions};
|
||
|
$args{exclusions} = _process_lists($params->{exclusions}) if defined $params->{exclusions};
|
||
|
|
||
|
my $flagtype = Bugzilla::FlagType->create(\%args);
|
||
|
|
||
|
return { id => $self->type('int', $flagtype->id) };
|
||
|
}
|
||
|
|
||
|
sub update {
|
||
|
my ($self, $params) = @_;
|
||
|
|
||
|
my $dbh = Bugzilla->dbh;
|
||
|
my $user = Bugzilla->user;
|
||
|
|
||
|
Bugzilla->login(LOGIN_REQUIRED);
|
||
|
$user->in_group('editcomponents')
|
||
|
|| scalar(@{$user->get_products_by_permission('editcomponents')})
|
||
|
|| ThrowUserError("auth_failure", { group => "editcomponents",
|
||
|
action => "edit",
|
||
|
object => "flagtypes" });
|
||
|
|
||
|
defined($params->{names}) || defined($params->{ids})
|
||
|
|| ThrowCodeError('params_required',
|
||
|
{ function => 'FlagType.update', params => ['ids', 'names'] });
|
||
|
|
||
|
# Get the list of unique flag type ids we are updating
|
||
|
my @flag_type_ids = defined($params->{ids}) ? @{$params->{ids}} : ();
|
||
|
if (defined $params->{names}) {
|
||
|
push @flag_type_ids, map { $_->id }
|
||
|
@{ Bugzilla::FlagType::match({ name => $params->{names} }) };
|
||
|
}
|
||
|
@flag_type_ids = uniq @flag_type_ids;
|
||
|
|
||
|
# We delete names and ids to keep only new values to set.
|
||
|
delete $params->{names};
|
||
|
delete $params->{ids};
|
||
|
|
||
|
# Process group inclusions and exclusions
|
||
|
# We removed them from $params because these are handled differently
|
||
|
my $inclusions = _process_lists(delete $params->{inclusions}) if defined $params->{inclusions};
|
||
|
my $exclusions = _process_lists(delete $params->{exclusions}) if defined $params->{exclusions};
|
||
|
|
||
|
$dbh->bz_start_transaction();
|
||
|
my %changes = ();
|
||
|
|
||
|
foreach my $flag_type_id (@flag_type_ids) {
|
||
|
my ($flagtype, $can_fully_edit) = $user->check_can_admin_flagtype($flag_type_id);
|
||
|
|
||
|
if ($can_fully_edit) {
|
||
|
$flagtype->set_all($params);
|
||
|
}
|
||
|
elsif (scalar keys %$params) {
|
||
|
ThrowUserError('flag_type_not_editable', { flagtype => $flagtype });
|
||
|
}
|
||
|
|
||
|
# Process the clusions
|
||
|
foreach my $type ('inclusions', 'exclusions') {
|
||
|
my $clusions = $type eq 'inclusions' ? $inclusions : $exclusions;
|
||
|
next if not defined $clusions;
|
||
|
|
||
|
my @extra_clusions = ();
|
||
|
if (!$user->in_group('editcomponents')) {
|
||
|
my $products = $user->get_products_by_permission('editcomponents');
|
||
|
# Bring back the products the user cannot edit.
|
||
|
foreach my $item (values %{$flagtype->$type}) {
|
||
|
my ($prod_id, $comp_id) = split(':', $item);
|
||
|
push(@extra_clusions, $item) unless grep { $_->id == $prod_id } @$products;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$flagtype->set_clusions({
|
||
|
$type => [@$clusions, @extra_clusions],
|
||
|
});
|
||
|
}
|
||
|
|
||
|
my $returned_changes = $flagtype->update();
|
||
|
$changes{$flagtype->id} = {
|
||
|
name => $flagtype->name,
|
||
|
changes => $returned_changes,
|
||
|
};
|
||
|
}
|
||
|
$dbh->bz_commit_transaction();
|
||
|
|
||
|
my @result;
|
||
|
foreach my $flag_type_id (keys %changes) {
|
||
|
my %hash = (
|
||
|
id => $self->type('int', $flag_type_id),
|
||
|
name => $self->type('string', $changes{$flag_type_id}{name}),
|
||
|
changes => {},
|
||
|
);
|
||
|
|
||
|
foreach my $field (keys %{ $changes{$flag_type_id}{changes} }) {
|
||
|
my $change = $changes{$flag_type_id}{changes}{$field};
|
||
|
$hash{changes}{$field} = {
|
||
|
removed => $self->type('string', $change->[0]),
|
||
|
added => $self->type('string', $change->[1])
|
||
|
};
|
||
|
}
|
||
|
|
||
|
push(@result, \%hash);
|
||
|
}
|
||
|
|
||
|
return { flagtypes => \@result };
|
||
|
}
|
||
|
|
||
|
sub _flagtype_to_hash {
|
||
|
my ($self, $flagtype, $product) = @_;
|
||
|
my $user = Bugzilla->user;
|
||
|
|
||
|
my @values = ('X');
|
||
|
push(@values, '?') if ($flagtype->is_requestable && $user->can_request_flag($flagtype));
|
||
|
push(@values, '+', '-') if $user->can_set_flag($flagtype);
|
||
|
|
||
|
my $item = {
|
||
|
id => $self->type('int' , $flagtype->id),
|
||
|
name => $self->type('string' , $flagtype->name),
|
||
|
description => $self->type('string' , $flagtype->description),
|
||
|
type => $self->type('string' , $flagtype->target_type),
|
||
|
values => \@values,
|
||
|
is_active => $self->type('boolean', $flagtype->is_active),
|
||
|
is_requesteeble => $self->type('boolean', $flagtype->is_requesteeble),
|
||
|
is_multiplicable => $self->type('boolean', $flagtype->is_multiplicable)
|
||
|
};
|
||
|
|
||
|
if ($product) {
|
||
|
my $inclusions = $self->_flagtype_clusions_to_hash($flagtype->inclusions, $product->id);
|
||
|
my $exclusions = $self->_flagtype_clusions_to_hash($flagtype->exclusions, $product->id);
|
||
|
# if we have both inclusions and exclusions, the exclusions are redundant
|
||
|
$exclusions = [] if @$inclusions && @$exclusions;
|
||
|
# no need to return anything if there's just "any component"
|
||
|
$item->{inclusions} = $inclusions if @$inclusions && $inclusions->[0] ne '';
|
||
|
$item->{exclusions} = $exclusions if @$exclusions && $exclusions->[0] ne '';
|
||
|
}
|
||
|
|
||
|
return $item;
|
||
|
}
|
||
|
|
||
|
sub _flagtype_clusions_to_hash {
|
||
|
my ($self, $clusions, $product_id) = @_;
|
||
|
my $result = [];
|
||
|
foreach my $key (keys %$clusions) {
|
||
|
my ($prod_id, $comp_id) = split(/:/, $clusions->{$key}, 2);
|
||
|
if ($prod_id == 0 || $prod_id == $product_id) {
|
||
|
if ($comp_id) {
|
||
|
push @$result, $comp_id;
|
||
|
}
|
||
|
else {
|
||
|
return [ '' ];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
$result = Bugzilla::Component->match({ product_id => $product_id, name => $result });
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
sub _process_lists {
|
||
|
my $list = shift;
|
||
|
my $user = Bugzilla->user;
|
||
|
|
||
|
my @products;
|
||
|
if ($user->in_group('editcomponents')) {
|
||
|
@products = Bugzilla::Product->get_all;
|
||
|
}
|
||
|
else {
|
||
|
@products = @{$user->get_products_by_permission('editcomponents')};
|
||
|
}
|
||
|
|
||
|
my @component_list;
|
||
|
|
||
|
foreach my $item (@$list) {
|
||
|
# A hash with products as the key and component names as the values
|
||
|
if(ref($item) eq 'HASH') {
|
||
|
while (my ($product_name, $component_names) = each %$item) {
|
||
|
my $product = Bugzilla::Product->check({name => $product_name});
|
||
|
unless (grep { $product->name eq $_->name } @products) {
|
||
|
ThrowUserError('product_access_denied', { name => $product_name });
|
||
|
}
|
||
|
my @component_ids;
|
||
|
|
||
|
foreach my $comp_name (@$component_names) {
|
||
|
my $component = Bugzilla::Component->check({product => $product, name => $comp_name});
|
||
|
ThrowCodeError('param_invalid', { param => $comp_name}) unless defined $component;
|
||
|
push @component_list, $product->id . ':' . $component->id;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
elsif(!ref($item)) {
|
||
|
# These are whole products
|
||
|
my $product = Bugzilla::Product->check({name => $item});
|
||
|
unless (grep { $product->name eq $_->name } @products) {
|
||
|
ThrowUserError('product_access_denied', { name => $item });
|
||
|
}
|
||
|
push @component_list, $product->id . ':0';
|
||
|
}
|
||
|
else {
|
||
|
# The user has passed something invalid
|
||
|
ThrowCodeError('param_invalid', { param => $item });
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return \@component_list;
|
||
|
}
|
||
|
|
||
|
1;
|
||
|
|
||
|
__END__
|
||
|
|
||
|
=head1 NAME
|
||
|
|
||
|
Bugzilla::WebService::FlagType - API for creating flags.
|
||
|
|
||
|
=head1 DESCRIPTION
|
||
|
|
||
|
This part of the Bugzilla API allows you to create new flags
|
||
|
|
||
|
=head1 METHODS
|
||
|
|
||
|
See L<Bugzilla::WebService> for a description of what B<STABLE>, B<UNSTABLE>,
|
||
|
and B<EXPERIMENTAL> mean, and for more description about error codes.
|
||
|
|
||
|
=head2 Get Flag Types
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<get> B<UNSTABLE>
|
||
|
|
||
|
=item B<Description>
|
||
|
|
||
|
Get information about valid flag types that can be set for bugs and attachments.
|
||
|
|
||
|
=item B<REST>
|
||
|
|
||
|
You have several options for retreiving information about flag types. The first
|
||
|
part is the request method and the rest is the related path needed.
|
||
|
|
||
|
To get information about all flag types for a product:
|
||
|
|
||
|
GET /rest/flag_type/<product>
|
||
|
|
||
|
To get information about flag_types for a product and component:
|
||
|
|
||
|
GET /rest/flag_type/<product>/<component>
|
||
|
|
||
|
The returned data format is the same as below.
|
||
|
|
||
|
=item B<Params>
|
||
|
|
||
|
You must pass a product name and an optional component name.
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<product> (string) - The name of a valid product.
|
||
|
|
||
|
=item C<component> (string) - An optional valid component name associated with the product.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<Returns>
|
||
|
|
||
|
A hash containing two keys, C<bug> and C<attachment>. Each key value is an array of hashes,
|
||
|
containing the following keys:
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<id>
|
||
|
|
||
|
C<int> An integer id uniquely identifying this flag type.
|
||
|
|
||
|
=item C<name>
|
||
|
|
||
|
C<string> The name for the flag type.
|
||
|
|
||
|
=item C<type>
|
||
|
|
||
|
C<string> The target of the flag type which is either C<bug> or C<attachment>.
|
||
|
|
||
|
=item C<description>
|
||
|
|
||
|
C<string> The description of the flag type.
|
||
|
|
||
|
=item C<values>
|
||
|
|
||
|
C<array> An array of string values that the user can set on the flag type.
|
||
|
|
||
|
=item C<is_requesteeble>
|
||
|
|
||
|
C<boolean> Users can ask specific other users to set flags of this type.
|
||
|
|
||
|
=item C<is_multiplicable>
|
||
|
|
||
|
C<boolean> Multiple flags of this type can be set for the same bug or attachment.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<Errors>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item 106 (Product Access Denied)
|
||
|
|
||
|
Either the product does not exist or you don't have access to it.
|
||
|
|
||
|
=item 51 (Invalid Component)
|
||
|
|
||
|
The component provided does not exist in the product.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<History>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item Added in Bugzilla B<5.0>.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head2 Create Flag
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<create> B<UNSTABLE>
|
||
|
|
||
|
=item B<Description>
|
||
|
|
||
|
Creates a new FlagType
|
||
|
|
||
|
=item B<REST>
|
||
|
|
||
|
POST /rest/flag_type
|
||
|
|
||
|
The params to include in the POST body as well as the returned data format,
|
||
|
are the same as below.
|
||
|
|
||
|
=item B<Params>
|
||
|
|
||
|
At a minimum the following two arguments must be supplied:
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<name> (string) - The name of the new Flag Type.
|
||
|
|
||
|
=item C<description> (string) - A description for the Flag Type object.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<Returns>
|
||
|
|
||
|
C<int> flag_id
|
||
|
|
||
|
The ID of the new FlagType object is returned.
|
||
|
|
||
|
=item B<Params>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item name B<required>
|
||
|
|
||
|
C<string> A short name identifying this type.
|
||
|
|
||
|
=item description B<required>
|
||
|
|
||
|
C<string> A comprehensive description of this type.
|
||
|
|
||
|
=item inclusions B<optional>
|
||
|
|
||
|
An array of strings or a hash containing product names, and optionally
|
||
|
component names. If you provide a string, the flag type will be shown on
|
||
|
all bugs in that product. If you provide a hash, the key represents the
|
||
|
product name, and the value is the components of the product to be included.
|
||
|
|
||
|
For example:
|
||
|
|
||
|
[ 'FooProduct',
|
||
|
{
|
||
|
BarProduct => [ 'C1', 'C3' ],
|
||
|
BazProduct => [ 'C7' ]
|
||
|
}
|
||
|
]
|
||
|
|
||
|
This flag will be added to B<All> components of I<FooProduct>,
|
||
|
components C1 and C3 of I<BarProduct>, and C7 of I<BazProduct>.
|
||
|
|
||
|
=item exclusions B<optional>
|
||
|
|
||
|
An array of strings or hashes containing product names. This uses the same
|
||
|
fromat as inclusions.
|
||
|
|
||
|
This will exclude the flag from all products and components specified.
|
||
|
|
||
|
=item sortkey B<optional>
|
||
|
|
||
|
C<int> A number between 1 and 32767 by which this type will be sorted when
|
||
|
displayed to users in a list; ignore if you don't care what order the types
|
||
|
appear in or if you want them to appear in alphabetical order.
|
||
|
|
||
|
=item is_active B<optional>
|
||
|
|
||
|
C<boolean> Flag of this type appear in the UI and can be set. Default is B<true>.
|
||
|
|
||
|
=item is_requestable B<optional>
|
||
|
|
||
|
C<boolean> Users can ask for flags of this type to be set. Default is B<true>.
|
||
|
|
||
|
=item cc_list B<optional>
|
||
|
|
||
|
C<array> An array of strings. If the flag type is requestable, who should
|
||
|
receive e-mail notification of requests. This is an array of e-mail addresses
|
||
|
which do not need to be Bugzilla logins.
|
||
|
|
||
|
=item is_specifically_requestable B<optional>
|
||
|
|
||
|
C<boolean> Users can ask specific other users to set flags of this type as
|
||
|
opposed to just asking the wind. Default is B<true>.
|
||
|
|
||
|
=item is_multiplicable B<optional>
|
||
|
|
||
|
C<boolean> Multiple flags of this type can be set on the same bug. Default is B<true>.
|
||
|
|
||
|
=item grant_group B<optional>
|
||
|
|
||
|
C<string> The group allowed to grant/deny flags of this type (to allow all
|
||
|
users to grant/deny these flags, select no group). Default is B<no group>.
|
||
|
|
||
|
=item request_group B<optional>
|
||
|
|
||
|
C<string> If flags of this type are requestable, the group allowed to request
|
||
|
them (to allow all users to request these flags, select no group). Note that
|
||
|
the request group alone has no effect if the grant group is not defined!
|
||
|
Default is B<no group>.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<Errors>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item 51 (Group Does Not Exist)
|
||
|
|
||
|
The group name you entered does not exist, or you do not have access to it.
|
||
|
|
||
|
=item 105 (Unknown component)
|
||
|
|
||
|
The component does not exist for this product.
|
||
|
|
||
|
=item 106 (Product Access Denied)
|
||
|
|
||
|
Either the product does not exist or you don't have editcomponents privileges
|
||
|
to it.
|
||
|
|
||
|
=item 501 (Illegal Email Address)
|
||
|
|
||
|
One of the e-mail address in the CC list is invalid. An e-mail in the CC
|
||
|
list does NOT need to be a valid Bugzilla user.
|
||
|
|
||
|
=item 1101 (Flag Type Name invalid)
|
||
|
|
||
|
You must specify a non-blank name for this flag type. It must
|
||
|
no contain spaces or commas, and must be 50 characters or less.
|
||
|
|
||
|
=item 1102 (Flag type must have description)
|
||
|
|
||
|
You must specify a description for this flag type.
|
||
|
|
||
|
=item 1103 (Flag type CC list is invalid
|
||
|
|
||
|
The CC list must be 200 characters or less.
|
||
|
|
||
|
=item 1104 (Flag Type Sort Key Not Valid)
|
||
|
|
||
|
The sort key is not a valid number.
|
||
|
|
||
|
=item 1105 (Flag Type Not Editable)
|
||
|
|
||
|
This flag type is not available for the products you can administer. Therefore
|
||
|
you can not edit attributes of the flag type, other than the inclusion and
|
||
|
exclusion list.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<History>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item Added in Bugzilla B<5.0>.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=back
|
||
|
|
||
|
=head2 update
|
||
|
|
||
|
B<EXPERIMENTAL>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item B<Description>
|
||
|
|
||
|
This allows you to update a flag type in Bugzilla.
|
||
|
|
||
|
=item B<REST>
|
||
|
|
||
|
PUT /rest/flag_type/<product_id_or_name>
|
||
|
|
||
|
The params to include in the PUT body as well as the returned data format,
|
||
|
are the same as below. The C<ids> and C<names> params will be overridden as
|
||
|
it is pulled from the URL path.
|
||
|
|
||
|
=item B<Params>
|
||
|
|
||
|
B<Note:> The following parameters specify which products you are updating.
|
||
|
You must set one or both of these parameters.
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<ids>
|
||
|
|
||
|
C<array> of C<int>s. Numeric ids of the flag types that you wish to update.
|
||
|
|
||
|
=item C<names>
|
||
|
|
||
|
C<array> of C<string>s. Names of the flag types that you wish to update. If
|
||
|
many flag types have the same name, this will change ALL of them.
|
||
|
|
||
|
=back
|
||
|
|
||
|
B<Note:> The following parameters specify the new values you want to set for
|
||
|
the products you are updating.
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item name
|
||
|
|
||
|
C<string> A short name identifying this type.
|
||
|
|
||
|
=item description
|
||
|
|
||
|
C<string> A comprehensive description of this type.
|
||
|
|
||
|
=item inclusions B<optional>
|
||
|
|
||
|
An array of strings or a hash containing product names, and optionally
|
||
|
component names. If you provide a string, the flag type will be shown on
|
||
|
all bugs in that product. If you provide a hash, the key represents the
|
||
|
product name, and the value is the components of the product to be included.
|
||
|
|
||
|
for example
|
||
|
|
||
|
[ 'FooProduct',
|
||
|
{
|
||
|
BarProduct => [ 'C1', 'C3' ],
|
||
|
BazProduct => [ 'C7' ]
|
||
|
}
|
||
|
]
|
||
|
|
||
|
This flag will be added to B<All> components of I<FooProduct>,
|
||
|
components C1 and C3 of I<BarProduct>, and C7 of I<BazProduct>.
|
||
|
|
||
|
=item exclusions B<optional>
|
||
|
|
||
|
An array of strings or hashes containing product names.
|
||
|
This uses the same fromat as inclusions.
|
||
|
|
||
|
This will exclude the flag from all products and components specified.
|
||
|
|
||
|
=item sortkey
|
||
|
|
||
|
C<int> A number between 1 and 32767 by which this type will be sorted when
|
||
|
displayed to users in a list; ignore if you don't care what order the types
|
||
|
appear in or if you want them to appear in alphabetical order.
|
||
|
|
||
|
=item is_active
|
||
|
|
||
|
C<boolean> Flag of this type appear in the UI and can be set.
|
||
|
|
||
|
=item is_requestable
|
||
|
|
||
|
C<boolean> Users can ask for flags of this type to be set.
|
||
|
|
||
|
=item cc_list
|
||
|
|
||
|
C<array> An array of strings. If the flag type is requestable, who should
|
||
|
receive e-mail notification of requests. This is an array of e-mail addresses
|
||
|
which do not need to be Bugzilla logins.
|
||
|
|
||
|
=item is_specifically_requestable
|
||
|
|
||
|
C<boolean> Users can ask specific other users to set flags of this type as
|
||
|
opposed to just asking the wind.
|
||
|
|
||
|
=item is_multiplicable
|
||
|
|
||
|
C<boolean> Multiple flags of this type can be set on the same bug.
|
||
|
|
||
|
=item grant_group
|
||
|
|
||
|
C<string> The group allowed to grant/deny flags of this type (to allow all
|
||
|
users to grant/deny these flags, select no group).
|
||
|
|
||
|
=item request_group
|
||
|
|
||
|
C<string> If flags of this type are requestable, the group allowed to request
|
||
|
them (to allow all users to request these flags, select no group). Note that
|
||
|
the request group alone has no effect if the grant group is not defined!
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<Returns>
|
||
|
|
||
|
A C<hash> with a single field "flagtypes". This points to an array of hashes
|
||
|
with the following fields:
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<id>
|
||
|
|
||
|
C<int> The id of the product that was updated.
|
||
|
|
||
|
=item C<name>
|
||
|
|
||
|
C<string> The name of the product that was updated.
|
||
|
|
||
|
=item C<changes>
|
||
|
|
||
|
C<hash> The changes that were actually done on this product. The keys are
|
||
|
the names of the fields that were changed, and the values are a hash
|
||
|
with two keys:
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item C<added>
|
||
|
|
||
|
C<string> The value that this field was changed to.
|
||
|
|
||
|
=item C<removed>
|
||
|
|
||
|
C<string> The value that was previously set in this field.
|
||
|
|
||
|
=back
|
||
|
|
||
|
Note that booleans will be represented with the strings '1' and '0'.
|
||
|
|
||
|
Here's an example of what a return value might look like:
|
||
|
|
||
|
{
|
||
|
products => [
|
||
|
{
|
||
|
id => 123,
|
||
|
changes => {
|
||
|
name => {
|
||
|
removed => 'FooFlagType',
|
||
|
added => 'BarFlagType'
|
||
|
},
|
||
|
is_requestable => {
|
||
|
removed => '1',
|
||
|
added => '0',
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<Errors>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item 51 (Group Does Not Exist)
|
||
|
|
||
|
The group name you entered does not exist, or you do not have access to it.
|
||
|
|
||
|
=item 105 (Unknown component)
|
||
|
|
||
|
The component does not exist for this product.
|
||
|
|
||
|
=item 106 (Product Access Denied)
|
||
|
|
||
|
Either the product does not exist or you don't have editcomponents privileges
|
||
|
to it.
|
||
|
|
||
|
=item 501 (Illegal Email Address)
|
||
|
|
||
|
One of the e-mail address in the CC list is invalid. An e-mail in the CC
|
||
|
list does NOT need to be a valid Bugzilla user.
|
||
|
|
||
|
=item 1101 (Flag Type Name invalid)
|
||
|
|
||
|
You must specify a non-blank name for this flag type. It must
|
||
|
no contain spaces or commas, and must be 50 characters or less.
|
||
|
|
||
|
=item 1102 (Flag type must have description)
|
||
|
|
||
|
You must specify a description for this flag type.
|
||
|
|
||
|
=item 1103 (Flag type CC list is invalid
|
||
|
|
||
|
The CC list must be 200 characters or less.
|
||
|
|
||
|
=item 1104 (Flag Type Sort Key Not Valid)
|
||
|
|
||
|
The sort key is not a valid number.
|
||
|
|
||
|
=item 1105 (Flag Type Not Editable)
|
||
|
|
||
|
This flag type is not available for the products you can administer. Therefore
|
||
|
you can not edit attributes of the flag type, other than the inclusion and
|
||
|
exclusion list.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=item B<History>
|
||
|
|
||
|
=over
|
||
|
|
||
|
=item Added in Bugzilla B<5.0>.
|
||
|
|
||
|
=back
|
||
|
|
||
|
=back
|