aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/FlagType.pm')
-rw-r--r--Bugzilla/FlagType.pm791
1 files changed, 405 insertions, 386 deletions
diff --git a/Bugzilla/FlagType.pm b/Bugzilla/FlagType.pm
index 72b3f64c1..a08ee83b9 100644
--- a/Bugzilla/FlagType.pm
+++ b/Bugzilla/FlagType.pm
@@ -49,113 +49,114 @@ use parent qw(Bugzilla::Object);
#### Initialization ####
###############################
-use constant DB_TABLE => 'flagtypes';
+use constant DB_TABLE => 'flagtypes';
use constant LIST_ORDER => 'sortkey, name';
use constant DB_COLUMNS => qw(
- id
- name
- description
- cc_list
- target_type
- sortkey
- is_active
- is_requestable
- is_requesteeble
- is_multiplicable
- grant_group_id
- request_group_id
+ id
+ name
+ description
+ cc_list
+ target_type
+ sortkey
+ is_active
+ is_requestable
+ is_requesteeble
+ is_multiplicable
+ grant_group_id
+ request_group_id
);
use constant UPDATE_COLUMNS => qw(
- name
- description
- cc_list
- sortkey
- is_active
- is_requestable
- is_requesteeble
- is_multiplicable
- grant_group_id
- request_group_id
+ name
+ description
+ cc_list
+ sortkey
+ is_active
+ is_requestable
+ is_requesteeble
+ is_multiplicable
+ grant_group_id
+ request_group_id
);
use constant VALIDATORS => {
- name => \&_check_name,
- description => \&_check_description,
- cc_list => \&_check_cc_list,
- target_type => \&_check_target_type,
- sortkey => \&_check_sortkey,
- is_active => \&Bugzilla::Object::check_boolean,
- is_requestable => \&Bugzilla::Object::check_boolean,
- is_requesteeble => \&Bugzilla::Object::check_boolean,
- is_multiplicable => \&Bugzilla::Object::check_boolean,
- grant_group => \&_check_group,
- request_group => \&_check_group,
+ name => \&_check_name,
+ description => \&_check_description,
+ cc_list => \&_check_cc_list,
+ target_type => \&_check_target_type,
+ sortkey => \&_check_sortkey,
+ is_active => \&Bugzilla::Object::check_boolean,
+ is_requestable => \&Bugzilla::Object::check_boolean,
+ is_requesteeble => \&Bugzilla::Object::check_boolean,
+ is_multiplicable => \&Bugzilla::Object::check_boolean,
+ grant_group => \&_check_group,
+ request_group => \&_check_group,
};
-use constant UPDATE_VALIDATORS => {
- grant_group_id => \&_check_group,
- request_group_id => \&_check_group,
-};
+use constant UPDATE_VALIDATORS =>
+ {grant_group_id => \&_check_group, request_group_id => \&_check_group,};
###############################
sub create {
- my $class = shift;
- my $dbh = Bugzilla->dbh;
+ my $class = shift;
+ my $dbh = Bugzilla->dbh;
+
+ $dbh->bz_start_transaction();
- $dbh->bz_start_transaction();
+ $class->check_required_create_fields(@_);
+ my $params = $class->run_create_validators(@_);
- $class->check_required_create_fields(@_);
- my $params = $class->run_create_validators(@_);
- # In the DB, only the first character of the target type is stored.
- $params->{target_type} = substr($params->{target_type}, 0, 1);
+ # In the DB, only the first character of the target type is stored.
+ $params->{target_type} = substr($params->{target_type}, 0, 1);
- # Extract everything which is not a valid column name.
- $params->{grant_group_id} = delete $params->{grant_group};
- $params->{request_group_id} = delete $params->{request_group};
- my $inclusions = delete $params->{inclusions};
- my $exclusions = delete $params->{exclusions};
+ # Extract everything which is not a valid column name.
+ $params->{grant_group_id} = delete $params->{grant_group};
+ $params->{request_group_id} = delete $params->{request_group};
+ my $inclusions = delete $params->{inclusions};
+ my $exclusions = delete $params->{exclusions};
- my $flagtype = $class->insert_create_data($params);
+ my $flagtype = $class->insert_create_data($params);
- $flagtype->set_clusions({ inclusions => $inclusions,
- exclusions => $exclusions });
- $flagtype->update();
+ $flagtype->set_clusions({inclusions => $inclusions, exclusions => $exclusions});
+ $flagtype->update();
- $dbh->bz_commit_transaction();
- return $flagtype;
+ $dbh->bz_commit_transaction();
+ return $flagtype;
}
sub update {
- my $self = shift;
- my $dbh = Bugzilla->dbh;
- my $flag_id = $self->id;
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
+ my $flag_id = $self->id;
- $dbh->bz_start_transaction();
- my $changes = $self->SUPER::update(@_);
+ $dbh->bz_start_transaction();
+ my $changes = $self->SUPER::update(@_);
- # Update the flaginclusions and flagexclusions tables.
- foreach my $category ('inclusions', 'exclusions') {
- next unless delete $self->{"_update_$category"};
+ # Update the flaginclusions and flagexclusions tables.
+ foreach my $category ('inclusions', 'exclusions') {
+ next unless delete $self->{"_update_$category"};
- $dbh->do("DELETE FROM flag$category WHERE type_id = ?", undef, $flag_id);
+ $dbh->do("DELETE FROM flag$category WHERE type_id = ?", undef, $flag_id);
- my $sth = $dbh->prepare("INSERT INTO flag$category
- (type_id, product_id, component_id) VALUES (?, ?, ?)");
+ my $sth = $dbh->prepare(
+ "INSERT INTO flag$category
+ (type_id, product_id, component_id) VALUES (?, ?, ?)"
+ );
- foreach my $prod_comp (values %{$self->{$category}}) {
- my ($prod_id, $comp_id) = split(':', $prod_comp);
- $prod_id ||= undef;
- $comp_id ||= undef;
- $sth->execute($flag_id, $prod_id, $comp_id);
- }
- $changes->{$category} = [0, 1];
+ foreach my $prod_comp (values %{$self->{$category}}) {
+ my ($prod_id, $comp_id) = split(':', $prod_comp);
+ $prod_id ||= undef;
+ $comp_id ||= undef;
+ $sth->execute($flag_id, $prod_id, $comp_id);
}
+ $changes->{$category} = [0, 1];
+ }
- # Clear existing flags for bugs/attachments in categories no longer on
- # the list of inclusions or that have been added to the list of exclusions.
- my $flag_ids = $dbh->selectcol_arrayref('SELECT DISTINCT flags.id
+ # Clear existing flags for bugs/attachments in categories no longer on
+ # the list of inclusions or that have been added to the list of exclusions.
+ my $flag_ids = $dbh->selectcol_arrayref(
+ 'SELECT DISTINCT flags.id
FROM flags
INNER JOIN bugs
ON flags.bug_id = bugs.bug_id
@@ -166,11 +167,13 @@ sub update {
AND (bugs.component_id = i.component_id
OR i.component_id IS NULL))
WHERE flags.type_id = ?
- AND i.type_id IS NULL',
- undef, $self->id);
- Bugzilla::Flag->force_retarget($flag_ids);
+ AND i.type_id IS NULL', undef,
+ $self->id
+ );
+ Bugzilla::Flag->force_retarget($flag_ids);
- $flag_ids = $dbh->selectcol_arrayref('SELECT DISTINCT flags.id
+ $flag_ids = $dbh->selectcol_arrayref(
+ 'SELECT DISTINCT flags.id
FROM flags
INNER JOIN bugs
ON flags.bug_id = bugs.bug_id
@@ -181,26 +184,29 @@ sub update {
OR e.product_id IS NULL)
AND (bugs.component_id = e.component_id
OR e.component_id IS NULL)',
- undef, $self->id);
- Bugzilla::Flag->force_retarget($flag_ids);
-
- # Silently remove requestees from flags which are no longer
- # specifically requestable.
- if (!$self->is_requesteeble) {
- my $ids = $dbh->selectcol_arrayref(
- 'SELECT id FROM flags WHERE type_id = ? AND requestee_id IS NOT NULL',
- undef, $self->id);
-
- if (@$ids) {
- $dbh->do('UPDATE flags SET requestee_id = NULL WHERE ' . $dbh->sql_in('id', $ids));
- foreach my $id (@$ids) {
- Bugzilla->memcached->clear({ table => 'flags', id => $id });
- }
- }
+ undef, $self->id
+ );
+ Bugzilla::Flag->force_retarget($flag_ids);
+
+ # Silently remove requestees from flags which are no longer
+ # specifically requestable.
+ if (!$self->is_requesteeble) {
+ my $ids
+ = $dbh->selectcol_arrayref(
+ 'SELECT id FROM flags WHERE type_id = ? AND requestee_id IS NOT NULL',
+ undef, $self->id);
+
+ if (@$ids) {
+ $dbh->do(
+ 'UPDATE flags SET requestee_id = NULL WHERE ' . $dbh->sql_in('id', $ids));
+ foreach my $id (@$ids) {
+ Bugzilla->memcached->clear({table => 'flags', id => $id});
+ }
}
+ }
- $dbh->bz_commit_transaction();
- return $changes;
+ $dbh->bz_commit_transaction();
+ return $changes;
}
###############################
@@ -259,172 +265,174 @@ Returns the sortkey of the flagtype.
=cut
-sub id { return $_[0]->{'id'}; }
-sub name { return $_[0]->{'name'}; }
-sub description { return $_[0]->{'description'}; }
-sub cc_list { return $_[0]->{'cc_list'}; }
-sub target_type { return $_[0]->{'target_type'} eq 'b' ? 'bug' : 'attachment'; }
-sub is_active { return $_[0]->{'is_active'}; }
-sub is_requestable { return $_[0]->{'is_requestable'}; }
-sub is_requesteeble { return $_[0]->{'is_requesteeble'}; }
+sub id { return $_[0]->{'id'}; }
+sub name { return $_[0]->{'name'}; }
+sub description { return $_[0]->{'description'}; }
+sub cc_list { return $_[0]->{'cc_list'}; }
+sub target_type { return $_[0]->{'target_type'} eq 'b' ? 'bug' : 'attachment'; }
+sub is_active { return $_[0]->{'is_active'}; }
+sub is_requestable { return $_[0]->{'is_requestable'}; }
+sub is_requesteeble { return $_[0]->{'is_requesteeble'}; }
sub is_multiplicable { return $_[0]->{'is_multiplicable'}; }
-sub sortkey { return $_[0]->{'sortkey'}; }
+sub sortkey { return $_[0]->{'sortkey'}; }
sub request_group_id { return $_[0]->{'request_group_id'}; }
-sub grant_group_id { return $_[0]->{'grant_group_id'}; }
+sub grant_group_id { return $_[0]->{'grant_group_id'}; }
################################
# Validators
################################
sub _check_name {
- my ($invocant, $name) = @_;
+ my ($invocant, $name) = @_;
- $name = trim($name);
- ($name && $name !~ /[\s,]/ && length($name) <= 50)
- || ThrowUserError('flag_type_name_invalid', { name => $name });
- return $name;
+ $name = trim($name);
+ ($name && $name !~ /[\s,]/ && length($name) <= 50)
+ || ThrowUserError('flag_type_name_invalid', {name => $name});
+ return $name;
}
sub _check_description {
- my ($invocant, $desc) = @_;
+ my ($invocant, $desc) = @_;
- $desc = trim($desc);
- $desc || ThrowUserError('flag_type_description_invalid');
- return $desc;
+ $desc = trim($desc);
+ $desc || ThrowUserError('flag_type_description_invalid');
+ return $desc;
}
sub _check_cc_list {
- my ($invocant, $cc_list) = @_;
-
- length($cc_list) <= 200
- || ThrowUserError('flag_type_cc_list_invalid', { cc_list => $cc_list });
-
- my @addresses = split(/[,\s]+/, $cc_list);
- my $addr_spec = $Email::Address::addr_spec;
- # We do not call check_email_syntax() because these addresses do not
- # require to match 'emailregexp' and do not depend on 'emailsuffix'.
- foreach my $address (@addresses) {
- ($address !~ /\P{ASCII}/ && $address =~ /^$addr_spec$/)
- || ThrowUserError('illegal_email_address',
- {addr => $address, default => 1});
- }
- return $cc_list;
+ my ($invocant, $cc_list) = @_;
+
+ length($cc_list) <= 200
+ || ThrowUserError('flag_type_cc_list_invalid', {cc_list => $cc_list});
+
+ my @addresses = split(/[,\s]+/, $cc_list);
+ my $addr_spec = $Email::Address::addr_spec;
+
+ # We do not call check_email_syntax() because these addresses do not
+ # require to match 'emailregexp' and do not depend on 'emailsuffix'.
+ foreach my $address (@addresses) {
+ ($address !~ /\P{ASCII}/ && $address =~ /^$addr_spec$/)
+ || ThrowUserError('illegal_email_address', {addr => $address, default => 1});
+ }
+ return $cc_list;
}
sub _check_target_type {
- my ($invocant, $target_type) = @_;
+ my ($invocant, $target_type) = @_;
- ($target_type eq 'bug' || $target_type eq 'attachment')
- || ThrowCodeError('flag_type_target_type_invalid', { target_type => $target_type });
- return $target_type;
+ ($target_type eq 'bug' || $target_type eq 'attachment')
+ || ThrowCodeError('flag_type_target_type_invalid',
+ {target_type => $target_type});
+ return $target_type;
}
sub _check_sortkey {
- my ($invocant, $sortkey) = @_;
+ my ($invocant, $sortkey) = @_;
- (detaint_natural($sortkey) && $sortkey <= MAX_SMALLINT)
- || ThrowUserError('flag_type_sortkey_invalid', { sortkey => $sortkey });
- return $sortkey;
+ (detaint_natural($sortkey) && $sortkey <= MAX_SMALLINT)
+ || ThrowUserError('flag_type_sortkey_invalid', {sortkey => $sortkey});
+ return $sortkey;
}
sub _check_group {
- my ($invocant, $group) = @_;
- return unless $group;
+ my ($invocant, $group) = @_;
+ return unless $group;
- trick_taint($group);
- $group = Bugzilla::Group->check($group);
- return $group->id;
+ trick_taint($group);
+ $group = Bugzilla::Group->check($group);
+ return $group->id;
}
###############################
#### Methods ####
###############################
-sub set_name { $_[0]->set('name', $_[1]); }
-sub set_description { $_[0]->set('description', $_[1]); }
-sub set_cc_list { $_[0]->set('cc_list', $_[1]); }
-sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
-sub set_is_active { $_[0]->set('is_active', $_[1]); }
-sub set_is_requestable { $_[0]->set('is_requestable', $_[1]); }
-sub set_is_specifically_requestable { $_[0]->set('is_requesteeble', $_[1]); }
-sub set_is_multiplicable { $_[0]->set('is_multiplicable', $_[1]); }
-sub set_grant_group { $_[0]->set('grant_group_id', $_[1]); }
-sub set_request_group { $_[0]->set('request_group_id', $_[1]); }
+sub set_name { $_[0]->set('name', $_[1]); }
+sub set_description { $_[0]->set('description', $_[1]); }
+sub set_cc_list { $_[0]->set('cc_list', $_[1]); }
+sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
+sub set_is_active { $_[0]->set('is_active', $_[1]); }
+sub set_is_requestable { $_[0]->set('is_requestable', $_[1]); }
+sub set_is_specifically_requestable { $_[0]->set('is_requesteeble', $_[1]); }
+sub set_is_multiplicable { $_[0]->set('is_multiplicable', $_[1]); }
+sub set_grant_group { $_[0]->set('grant_group_id', $_[1]); }
+sub set_request_group { $_[0]->set('request_group_id', $_[1]); }
sub set_clusions {
- my ($self, $list) = @_;
- my $user = Bugzilla->user;
- my %products;
- my $params = {};
-
- # If the user has editcomponents privs, then we only need to make sure
- # that the product exists.
- if ($user->in_group('editcomponents')) {
- $params->{allow_inaccessible} = 1;
- }
-
- foreach my $category (keys %$list) {
- my %clusions;
- my %clusions_as_hash;
-
- foreach my $prod_comp (@{$list->{$category} || []}) {
- my ($prod_id, $comp_id) = split(':', $prod_comp);
- my $prod_name = '__Any__';
- my $comp_name = '__Any__';
- # Does the product exist?
- if ($prod_id) {
- detaint_natural($prod_id)
- || ThrowCodeError('param_must_be_numeric',
- { function => 'Bugzilla::FlagType::set_clusions' });
-
- if (!$products{$prod_id}) {
- $params->{id} = $prod_id;
- $products{$prod_id} = Bugzilla::Product->check($params);
- }
- $prod_name = $products{$prod_id}->name;
-
- # Does the component belong to this product?
- if ($comp_id) {
- detaint_natural($comp_id)
- || ThrowCodeError('param_must_be_numeric',
- { function => 'Bugzilla::FlagType::set_clusions' });
-
- my ($component) = grep { $_->id == $comp_id } @{$products{$prod_id}->components}
- or ThrowUserError('product_unknown_component',
- { product => $prod_name, comp_id => $comp_id });
- $comp_name = $component->name;
- }
- else {
- $comp_id = 0;
- }
- }
- else {
- $prod_id = 0;
- $comp_id = 0;
- }
- $clusions{"$prod_name:$comp_name"} = "$prod_id:$comp_id";
- $clusions_as_hash{$prod_id}->{$comp_id} = 1;
+ my ($self, $list) = @_;
+ my $user = Bugzilla->user;
+ my %products;
+ my $params = {};
+
+ # If the user has editcomponents privs, then we only need to make sure
+ # that the product exists.
+ if ($user->in_group('editcomponents')) {
+ $params->{allow_inaccessible} = 1;
+ }
+
+ foreach my $category (keys %$list) {
+ my %clusions;
+ my %clusions_as_hash;
+
+ foreach my $prod_comp (@{$list->{$category} || []}) {
+ my ($prod_id, $comp_id) = split(':', $prod_comp);
+ my $prod_name = '__Any__';
+ my $comp_name = '__Any__';
+
+ # Does the product exist?
+ if ($prod_id) {
+ detaint_natural($prod_id)
+ || ThrowCodeError('param_must_be_numeric',
+ {function => 'Bugzilla::FlagType::set_clusions'});
+
+ if (!$products{$prod_id}) {
+ $params->{id} = $prod_id;
+ $products{$prod_id} = Bugzilla::Product->check($params);
}
-
- # Check the user has the editcomponent permission on products that are changing
- if (! $user->in_group('editcomponents')) {
- my $current_clusions = $self->$category;
- my ($removed, $added)
- = diff_arrays([ values %$current_clusions ], [ values %clusions ]);
- my @changed_product_ids
- = uniq map { substr($_, 0, index($_, ':')) } @$removed, @$added;
- foreach my $product_id (@changed_product_ids) {
- $user->in_group('editcomponents', $product_id)
- || ThrowUserError('product_access_denied',
- { name => $products{$product_id}->name });
- }
+ $prod_name = $products{$prod_id}->name;
+
+ # Does the component belong to this product?
+ if ($comp_id) {
+ detaint_natural($comp_id)
+ || ThrowCodeError('param_must_be_numeric',
+ {function => 'Bugzilla::FlagType::set_clusions'});
+
+ my ($component) = grep { $_->id == $comp_id } @{$products{$prod_id}->components}
+ or ThrowUserError('product_unknown_component',
+ {product => $prod_name, comp_id => $comp_id});
+ $comp_name = $component->name;
+ }
+ else {
+ $comp_id = 0;
}
+ }
+ else {
+ $prod_id = 0;
+ $comp_id = 0;
+ }
+ $clusions{"$prod_name:$comp_name"} = "$prod_id:$comp_id";
+ $clusions_as_hash{$prod_id}->{$comp_id} = 1;
+ }
- # Set the changes
- $self->{$category} = \%clusions;
- $self->{"${category}_as_hash"} = \%clusions_as_hash;
- $self->{"_update_$category"} = 1;
+ # Check the user has the editcomponent permission on products that are changing
+ if (!$user->in_group('editcomponents')) {
+ my $current_clusions = $self->$category;
+ my ($removed, $added)
+ = diff_arrays([values %$current_clusions], [values %clusions]);
+ my @changed_product_ids = uniq map { substr($_, 0, index($_, ':')) } @$removed,
+ @$added;
+ foreach my $product_id (@changed_product_ids) {
+ $user->in_group('editcomponents', $product_id)
+ || ThrowUserError('product_access_denied',
+ {name => $products{$product_id}->name});
+ }
}
+
+ # Set the changes
+ $self->{$category} = \%clusions;
+ $self->{"${category}_as_hash"} = \%clusions_as_hash;
+ $self->{"_update_$category"} = 1;
+ }
}
=pod
@@ -465,76 +473,79 @@ explicitly excluded from the flagtype.
=cut
sub grant_list {
- my $self = shift;
- require Bugzilla::User;
- my @custusers;
- my @allusers = @{Bugzilla->user->get_userlist};
- foreach my $user (@allusers) {
- my $user_obj = new Bugzilla::User({name => $user->{login}});
- push(@custusers, $user) if $user_obj->can_set_flag($self);
- }
- return \@custusers;
+ my $self = shift;
+ require Bugzilla::User;
+ my @custusers;
+ my @allusers = @{Bugzilla->user->get_userlist};
+ foreach my $user (@allusers) {
+ my $user_obj = new Bugzilla::User({name => $user->{login}});
+ push(@custusers, $user) if $user_obj->can_set_flag($self);
+ }
+ return \@custusers;
}
sub grant_group {
- my $self = shift;
+ my $self = shift;
- if (!defined $self->{'grant_group'} && $self->{'grant_group_id'}) {
- $self->{'grant_group'} = new Bugzilla::Group($self->{'grant_group_id'});
- }
- return $self->{'grant_group'};
+ if (!defined $self->{'grant_group'} && $self->{'grant_group_id'}) {
+ $self->{'grant_group'} = new Bugzilla::Group($self->{'grant_group_id'});
+ }
+ return $self->{'grant_group'};
}
sub request_group {
- my $self = shift;
+ my $self = shift;
- if (!defined $self->{'request_group'} && $self->{'request_group_id'}) {
- $self->{'request_group'} = new Bugzilla::Group($self->{'request_group_id'});
- }
- return $self->{'request_group'};
+ if (!defined $self->{'request_group'} && $self->{'request_group_id'}) {
+ $self->{'request_group'} = new Bugzilla::Group($self->{'request_group_id'});
+ }
+ return $self->{'request_group'};
}
sub flag_count {
- my $self = shift;
-
- if (!defined $self->{'flag_count'}) {
- $self->{'flag_count'} =
- Bugzilla->dbh->selectrow_array('SELECT COUNT(*) FROM flags
- WHERE type_id = ?', undef, $self->{'id'});
- }
- return $self->{'flag_count'};
+ my $self = shift;
+
+ if (!defined $self->{'flag_count'}) {
+ $self->{'flag_count'} = Bugzilla->dbh->selectrow_array(
+ 'SELECT COUNT(*) FROM flags
+ WHERE type_id = ?', undef, $self->{'id'}
+ );
+ }
+ return $self->{'flag_count'};
}
sub inclusions {
- my $self = shift;
+ my $self = shift;
- if (!defined $self->{inclusions}) {
- ($self->{inclusions}, $self->{inclusions_as_hash}) = get_clusions($self->id, 'in');
- }
- return $self->{inclusions};
+ if (!defined $self->{inclusions}) {
+ ($self->{inclusions}, $self->{inclusions_as_hash})
+ = get_clusions($self->id, 'in');
+ }
+ return $self->{inclusions};
}
sub inclusions_as_hash {
- my $self = shift;
+ my $self = shift;
- $self->inclusions unless defined $self->{inclusions_as_hash};
- return $self->{inclusions_as_hash};
+ $self->inclusions unless defined $self->{inclusions_as_hash};
+ return $self->{inclusions_as_hash};
}
sub exclusions {
- my $self = shift;
+ my $self = shift;
- if (!defined $self->{exclusions}) {
- ($self->{exclusions}, $self->{exclusions_as_hash}) = get_clusions($self->id, 'ex');
- }
- return $self->{exclusions};
+ if (!defined $self->{exclusions}) {
+ ($self->{exclusions}, $self->{exclusions_as_hash})
+ = get_clusions($self->id, 'ex');
+ }
+ return $self->{exclusions};
}
sub exclusions_as_hash {
- my $self = shift;
+ my $self = shift;
- $self->exclusions unless defined $self->{exclusions_as_hash};
- return $self->{exclusions_as_hash};
+ $self->exclusions unless defined $self->{exclusions_as_hash};
+ return $self->{exclusions_as_hash};
}
######################################################################
@@ -558,11 +569,11 @@ $clusions{'product_name:component_name'} = "product_ID:component_ID"
=cut
sub get_clusions {
- my ($id, $type) = @_;
- my $dbh = Bugzilla->dbh;
+ my ($id, $type) = @_;
+ my $dbh = Bugzilla->dbh;
- my $list =
- $dbh->selectall_arrayref("SELECT products.id, products.name,
+ my $list = $dbh->selectall_arrayref(
+ "SELECT products.id, products.name,
components.id, components.name
FROM flagtypes
INNER JOIN flag${type}clusions
@@ -571,19 +582,19 @@ sub get_clusions {
ON flag${type}clusions.product_id = products.id
LEFT JOIN components
ON flag${type}clusions.component_id = components.id
- WHERE flagtypes.id = ?",
- undef, $id);
- my (%clusions, %clusions_as_hash);
- foreach my $data (@$list) {
- my ($product_id, $product_name, $component_id, $component_name) = @$data;
- $product_id ||= 0;
- $product_name ||= "__Any__";
- $component_id ||= 0;
- $component_name ||= "__Any__";
- $clusions{"$product_name:$component_name"} = "$product_id:$component_id";
- $clusions_as_hash{$product_id}->{$component_id} = 1;
- }
- return (\%clusions, \%clusions_as_hash);
+ WHERE flagtypes.id = ?", undef, $id
+ );
+ my (%clusions, %clusions_as_hash);
+ foreach my $data (@$list) {
+ my ($product_id, $product_name, $component_id, $component_name) = @$data;
+ $product_id ||= 0;
+ $product_name ||= "__Any__";
+ $component_id ||= 0;
+ $component_name ||= "__Any__";
+ $clusions{"$product_name:$component_name"} = "$product_id:$component_id";
+ $clusions_as_hash{$product_id}->{$component_id} = 1;
+ }
+ return (\%clusions, \%clusions_as_hash);
}
=pod
@@ -600,18 +611,19 @@ and returns a list of matching flagtype objects.
=cut
sub match {
- my ($criteria) = @_;
- my $dbh = Bugzilla->dbh;
+ my ($criteria) = @_;
+ my $dbh = Bugzilla->dbh;
- # Depending on the criteria, we may have to append additional tables.
- my $tables = [DB_TABLE];
- my @criteria = sqlify_criteria($criteria, $tables);
- $tables = join(' ', @$tables);
- $criteria = join(' AND ', @criteria);
+ # Depending on the criteria, we may have to append additional tables.
+ my $tables = [DB_TABLE];
+ my @criteria = sqlify_criteria($criteria, $tables);
+ $tables = join(' ', @$tables);
+ $criteria = join(' AND ', @criteria);
- my $flagtype_ids = $dbh->selectcol_arrayref("SELECT id FROM $tables WHERE $criteria");
+ my $flagtype_ids
+ = $dbh->selectcol_arrayref("SELECT id FROM $tables WHERE $criteria");
- return Bugzilla::FlagType->new_from_list($flagtype_ids);
+ return Bugzilla::FlagType->new_from_list($flagtype_ids);
}
=pod
@@ -627,18 +639,20 @@ Returns the total number of flag types matching the given criteria.
=cut
sub count {
- my ($criteria) = @_;
- my $dbh = Bugzilla->dbh;
-
- # Depending on the criteria, we may have to append additional tables.
- my $tables = [DB_TABLE];
- my @criteria = sqlify_criteria($criteria, $tables);
- $tables = join(' ', @$tables);
- $criteria = join(' AND ', @criteria);
-
- my $count = $dbh->selectrow_array("SELECT COUNT(flagtypes.id)
- FROM $tables WHERE $criteria");
- return $count;
+ my ($criteria) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ # Depending on the criteria, we may have to append additional tables.
+ my $tables = [DB_TABLE];
+ my @criteria = sqlify_criteria($criteria, $tables);
+ $tables = join(' ', @$tables);
+ $criteria = join(' AND ', @criteria);
+
+ my $count = $dbh->selectrow_array(
+ "SELECT COUNT(flagtypes.id)
+ FROM $tables WHERE $criteria"
+ );
+ return $count;
}
######################################################################
@@ -646,93 +660,98 @@ sub count {
######################################################################
# Converts a hash of criteria into a list of SQL criteria.
-# $criteria is a reference to the criteria (field => value),
-# $tables is a reference to an array of tables being accessed
+# $criteria is a reference to the criteria (field => value),
+# $tables is a reference to an array of tables being accessed
# by the query.
sub sqlify_criteria {
- my ($criteria, $tables) = @_;
- my $dbh = Bugzilla->dbh;
-
- # the generated list of SQL criteria; "1=1" is a clever way of making sure
- # there's something in the list so calling code doesn't have to check list
- # size before building a WHERE clause out of it
- my @criteria = ("1=1");
-
- if ($criteria->{name}) {
- if (ref($criteria->{name}) eq 'ARRAY') {
- my @names = map { $dbh->quote($_) } @{$criteria->{name}};
- # Detaint data as we have quoted it.
- foreach my $name (@names) {
- trick_taint($name);
- }
- push @criteria, $dbh->sql_in('flagtypes.name', \@names);
- }
- else {
- my $name = $dbh->quote($criteria->{name});
- trick_taint($name); # Detaint data as we have quoted it.
- push(@criteria, "flagtypes.name = $name");
- }
+ my ($criteria, $tables) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ # the generated list of SQL criteria; "1=1" is a clever way of making sure
+ # there's something in the list so calling code doesn't have to check list
+ # size before building a WHERE clause out of it
+ my @criteria = ("1=1");
+
+ if ($criteria->{name}) {
+ if (ref($criteria->{name}) eq 'ARRAY') {
+ my @names = map { $dbh->quote($_) } @{$criteria->{name}};
+
+ # Detaint data as we have quoted it.
+ foreach my $name (@names) {
+ trick_taint($name);
+ }
+ push @criteria, $dbh->sql_in('flagtypes.name', \@names);
}
- if ($criteria->{target_type}) {
- # The target type is stored in the database as a one-character string
- # ("a" for attachment and "b" for bug), but this function takes complete
- # names ("attachment" and "bug") for clarity, so we must convert them.
- my $target_type = $criteria->{target_type} eq 'bug'? 'b' : 'a';
- push(@criteria, "flagtypes.target_type = '$target_type'");
+ else {
+ my $name = $dbh->quote($criteria->{name});
+ trick_taint($name); # Detaint data as we have quoted it.
+ push(@criteria, "flagtypes.name = $name");
}
- if (exists($criteria->{is_active})) {
- my $is_active = $criteria->{is_active} ? "1" : "0";
- push(@criteria, "flagtypes.is_active = $is_active");
- }
- if ($criteria->{product_id}) {
- my $product_id = $criteria->{product_id};
- detaint_natural($product_id)
- || ThrowCodeError('bad_arg', { argument => 'product_id',
- function => 'Bugzilla::FlagType::sqlify_criteria' });
-
- # Add inclusions to the query, which simply involves joining the table
- # by flag type ID and target product/component.
- push(@$tables, "INNER JOIN flaginclusions AS i ON flagtypes.id = i.type_id");
- push(@criteria, "(i.product_id = $product_id OR i.product_id IS NULL)");
-
- # Add exclusions to the query, which is more complicated. First of all,
- # we do a LEFT JOIN so we don't miss flag types with no exclusions.
- # Then, as with inclusions, we join on flag type ID and target product/
- # component. However, since we want flag types that *aren't* on the
- # exclusions list, we add a WHERE criteria to use only records with
- # NULL exclusion type, i.e. without any exclusions.
- my $join_clause = "flagtypes.id = e.type_id ";
-
- my $addl_join_clause = "";
- if ($criteria->{component_id}) {
- my $component_id = $criteria->{component_id};
- detaint_natural($component_id)
- || ThrowCodeError('bad_arg', { argument => 'component_id',
- function => 'Bugzilla::FlagType::sqlify_criteria' });
-
- push(@criteria, "(i.component_id = $component_id OR i.component_id IS NULL)");
- $join_clause .= "AND (e.component_id = $component_id OR e.component_id IS NULL) ";
- }
- else {
- $addl_join_clause = "AND e.component_id IS NULL OR (i.component_id = e.component_id) ";
- }
- $join_clause .= "AND ((e.product_id = $product_id $addl_join_clause) OR e.product_id IS NULL)";
-
- push(@$tables, "LEFT JOIN flagexclusions AS e ON ($join_clause)");
- push(@criteria, "e.type_id IS NULL");
+ }
+ if ($criteria->{target_type}) {
+
+ # The target type is stored in the database as a one-character string
+ # ("a" for attachment and "b" for bug), but this function takes complete
+ # names ("attachment" and "bug") for clarity, so we must convert them.
+ my $target_type = $criteria->{target_type} eq 'bug' ? 'b' : 'a';
+ push(@criteria, "flagtypes.target_type = '$target_type'");
+ }
+ if (exists($criteria->{is_active})) {
+ my $is_active = $criteria->{is_active} ? "1" : "0";
+ push(@criteria, "flagtypes.is_active = $is_active");
+ }
+ if ($criteria->{product_id}) {
+ my $product_id = $criteria->{product_id};
+ detaint_natural($product_id)
+ || ThrowCodeError('bad_arg',
+ {argument => 'product_id', function => 'Bugzilla::FlagType::sqlify_criteria'});
+
+ # Add inclusions to the query, which simply involves joining the table
+ # by flag type ID and target product/component.
+ push(@$tables, "INNER JOIN flaginclusions AS i ON flagtypes.id = i.type_id");
+ push(@criteria, "(i.product_id = $product_id OR i.product_id IS NULL)");
+
+ # Add exclusions to the query, which is more complicated. First of all,
+ # we do a LEFT JOIN so we don't miss flag types with no exclusions.
+ # Then, as with inclusions, we join on flag type ID and target product/
+ # component. However, since we want flag types that *aren't* on the
+ # exclusions list, we add a WHERE criteria to use only records with
+ # NULL exclusion type, i.e. without any exclusions.
+ my $join_clause = "flagtypes.id = e.type_id ";
+
+ my $addl_join_clause = "";
+ if ($criteria->{component_id}) {
+ my $component_id = $criteria->{component_id};
+ detaint_natural($component_id) || ThrowCodeError('bad_arg',
+ {argument => 'component_id', function => 'Bugzilla::FlagType::sqlify_criteria'}
+ );
+
+ push(@criteria, "(i.component_id = $component_id OR i.component_id IS NULL)");
+ $join_clause
+ .= "AND (e.component_id = $component_id OR e.component_id IS NULL) ";
}
- if ($criteria->{group}) {
- my $gid = $criteria->{group};
- detaint_natural($gid)
- || ThrowCodeError('bad_arg', { argument => 'group',
- function => 'Bugzilla::FlagType::sqlify_criteria' });
-
- push(@criteria, "(flagtypes.grant_group_id = $gid " .
- " OR flagtypes.request_group_id = $gid)");
+ else {
+ $addl_join_clause
+ = "AND e.component_id IS NULL OR (i.component_id = e.component_id) ";
}
-
- return @criteria;
+ $join_clause
+ .= "AND ((e.product_id = $product_id $addl_join_clause) OR e.product_id IS NULL)";
+
+ push(@$tables, "LEFT JOIN flagexclusions AS e ON ($join_clause)");
+ push(@criteria, "e.type_id IS NULL");
+ }
+ if ($criteria->{group}) {
+ my $gid = $criteria->{group};
+ detaint_natural($gid)
+ || ThrowCodeError('bad_arg',
+ {argument => 'group', function => 'Bugzilla::FlagType::sqlify_criteria'});
+
+ push(@criteria,
+ "(flagtypes.grant_group_id = $gid " . " OR flagtypes.request_group_id = $gid)");
+ }
+
+ return @criteria;
}
1;