aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Component.pm')
-rw-r--r--Bugzilla/Component.pm540
1 files changed, 279 insertions, 261 deletions
diff --git a/Bugzilla/Component.pm b/Bugzilla/Component.pm
index d5a6ece5d..ef8180eb0 100644
--- a/Bugzilla/Component.pm
+++ b/Bugzilla/Component.pm
@@ -27,150 +27,147 @@ use Scalar::Util qw(blessed);
###############################
use constant DB_TABLE => 'components';
+
# This is mostly for the editfields.cgi case where ->get_all is called.
use constant LIST_ORDER => 'product_id, name';
use constant DB_COLUMNS => qw(
- id
- name
- product_id
- initialowner
- initialqacontact
- description
- isactive
+ id
+ name
+ product_id
+ initialowner
+ initialqacontact
+ description
+ isactive
);
use constant UPDATE_COLUMNS => qw(
- name
- initialowner
- initialqacontact
- description
- isactive
+ name
+ initialowner
+ initialqacontact
+ description
+ isactive
);
-use constant REQUIRED_FIELD_MAP => {
- product_id => 'product',
-};
+use constant REQUIRED_FIELD_MAP => {product_id => 'product',};
use constant VALIDATORS => {
- create_series => \&Bugzilla::Object::check_boolean,
- product => \&_check_product,
- initialowner => \&_check_initialowner,
- initialqacontact => \&_check_initialqacontact,
- description => \&_check_description,
- initial_cc => \&_check_cc_list,
- name => \&_check_name,
- isactive => \&Bugzilla::Object::check_boolean,
+ create_series => \&Bugzilla::Object::check_boolean,
+ product => \&_check_product,
+ initialowner => \&_check_initialowner,
+ initialqacontact => \&_check_initialqacontact,
+ description => \&_check_description,
+ initial_cc => \&_check_cc_list,
+ name => \&_check_name,
+ isactive => \&Bugzilla::Object::check_boolean,
};
-use constant VALIDATOR_DEPENDENCIES => {
- name => ['product'],
-};
+use constant VALIDATOR_DEPENDENCIES => {name => ['product'],};
###############################
sub new {
- my $class = shift;
- my $param = shift;
- my $dbh = Bugzilla->dbh;
-
- my $product;
- if (ref $param and !defined $param->{id}) {
- $product = $param->{product};
- my $name = $param->{name};
- if (!defined $product) {
- ThrowCodeError('bad_arg',
- {argument => 'product',
- function => "${class}::new"});
- }
- if (!defined $name) {
- ThrowCodeError('bad_arg',
- {argument => 'name',
- function => "${class}::new"});
- }
-
- my $condition = 'product_id = ? AND name = ?';
- my @values = ($product->id, $name);
- $param = { condition => $condition, values => \@values };
+ my $class = shift;
+ my $param = shift;
+ my $dbh = Bugzilla->dbh;
+
+ my $product;
+ if (ref $param and !defined $param->{id}) {
+ $product = $param->{product};
+ my $name = $param->{name};
+ if (!defined $product) {
+ ThrowCodeError('bad_arg', {argument => 'product', function => "${class}::new"});
}
+ if (!defined $name) {
+ ThrowCodeError('bad_arg', {argument => 'name', function => "${class}::new"});
+ }
+
+ my $condition = 'product_id = ? AND name = ?';
+ my @values = ($product->id, $name);
+ $param = {condition => $condition, values => \@values};
+ }
- unshift @_, $param;
- my $component = $class->SUPER::new(@_);
- # Add the product object as attribute only if the component exists.
- $component->{product} = $product if ($component && $product);
- return $component;
+ unshift @_, $param;
+ my $component = $class->SUPER::new(@_);
+
+ # Add the product object as attribute only if the component exists.
+ $component->{product} = $product if ($component && $product);
+ return $component;
}
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(@_);
- my $cc_list = delete $params->{initial_cc};
- my $create_series = delete $params->{create_series};
- my $product = delete $params->{product};
- $params->{product_id} = $product->id;
+ $class->check_required_create_fields(@_);
+ my $params = $class->run_create_validators(@_);
+ my $cc_list = delete $params->{initial_cc};
+ my $create_series = delete $params->{create_series};
+ my $product = delete $params->{product};
+ $params->{product_id} = $product->id;
- my $component = $class->insert_create_data($params);
- $component->{product} = $product;
+ my $component = $class->insert_create_data($params);
+ $component->{product} = $product;
- # We still have to fill the component_cc table.
- $component->_update_cc_list($cc_list) if $cc_list;
+ # We still have to fill the component_cc table.
+ $component->_update_cc_list($cc_list) if $cc_list;
- # Create series for the new component.
- $component->_create_series() if $create_series;
+ # Create series for the new component.
+ $component->_create_series() if $create_series;
- $dbh->bz_commit_transaction();
- return $component;
+ $dbh->bz_commit_transaction();
+ return $component;
}
sub update {
- my $self = shift;
- my $changes = $self->SUPER::update(@_);
-
- # Update the component_cc table if necessary.
- if (defined $self->{cc_ids}) {
- my $diff = $self->_update_cc_list($self->{cc_ids});
- $changes->{cc_list} = $diff if defined $diff;
- }
- return $changes;
+ my $self = shift;
+ my $changes = $self->SUPER::update(@_);
+
+ # Update the component_cc table if necessary.
+ if (defined $self->{cc_ids}) {
+ my $diff = $self->_update_cc_list($self->{cc_ids});
+ $changes->{cc_list} = $diff if defined $diff;
+ }
+ return $changes;
}
sub remove_from_db {
- my $self = shift;
- my $dbh = Bugzilla->dbh;
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
- $self->_check_if_controller(); # From ChoiceInterface
+ $self->_check_if_controller(); # From ChoiceInterface
- $dbh->bz_start_transaction();
+ $dbh->bz_start_transaction();
- # Products must have at least one component.
- my @components = @{ $self->product->components };
- if (scalar(@components) == 1) {
- ThrowUserError('component_is_last', { comp => $self });
- }
+ # Products must have at least one component.
+ my @components = @{$self->product->components};
+ if (scalar(@components) == 1) {
+ ThrowUserError('component_is_last', {comp => $self});
+ }
+
+ if ($self->bug_count) {
+ if (Bugzilla->params->{'allowbugdeletion'}) {
+ require Bugzilla::Bug;
+ foreach my $bug_id (@{$self->bug_ids}) {
- if ($self->bug_count) {
- if (Bugzilla->params->{'allowbugdeletion'}) {
- require Bugzilla::Bug;
- foreach my $bug_id (@{$self->bug_ids}) {
- # Note: We allow admins to delete bugs even if they can't
- # see them, as long as they can see the product.
- my $bug = new Bugzilla::Bug($bug_id);
- $bug->remove_from_db();
- }
- } else {
- ThrowUserError('component_has_bugs', {nb => $self->bug_count});
- }
+ # Note: We allow admins to delete bugs even if they can't
+ # see them, as long as they can see the product.
+ my $bug = new Bugzilla::Bug($bug_id);
+ $bug->remove_from_db();
+ }
}
- # Update the list of components in the product object.
- $self->product->{components} = [grep { $_->id != $self->id } @components];
- $self->SUPER::remove_from_db();
+ else {
+ ThrowUserError('component_has_bugs', {nb => $self->bug_count});
+ }
+ }
+
+ # Update the list of components in the product object.
+ $self->product->{components} = [grep { $_->id != $self->id } @components];
+ $self->SUPER::remove_from_db();
- $dbh->bz_commit_transaction();
+ $dbh->bz_commit_transaction();
}
################################
@@ -178,69 +175,70 @@ sub remove_from_db {
################################
sub _check_name {
- my ($invocant, $name, undef, $params) = @_;
- my $product = blessed($invocant) ? $invocant->product : $params->{product};
-
- $name = trim($name);
- $name || ThrowUserError('component_blank_name');
-
- if (length($name) > MAX_COMPONENT_SIZE) {
- ThrowUserError('component_name_too_long', {'name' => $name});
- }
-
- my $component = new Bugzilla::Component({product => $product, name => $name});
- if ($component && (!ref $invocant || $component->id != $invocant->id)) {
- ThrowUserError('component_already_exists', { name => $component->name,
- product => $product });
- }
- return $name;
+ my ($invocant, $name, undef, $params) = @_;
+ my $product = blessed($invocant) ? $invocant->product : $params->{product};
+
+ $name = trim($name);
+ $name || ThrowUserError('component_blank_name');
+
+ if (length($name) > MAX_COMPONENT_SIZE) {
+ ThrowUserError('component_name_too_long', {'name' => $name});
+ }
+
+ my $component = new Bugzilla::Component({product => $product, name => $name});
+ if ($component && (!ref $invocant || $component->id != $invocant->id)) {
+ ThrowUserError('component_already_exists',
+ {name => $component->name, product => $product});
+ }
+ return $name;
}
sub _check_description {
- my ($invocant, $description) = @_;
+ my ($invocant, $description) = @_;
- $description = trim($description);
- $description || ThrowUserError('component_blank_description');
- return $description;
+ $description = trim($description);
+ $description || ThrowUserError('component_blank_description');
+ return $description;
}
sub _check_initialowner {
- my ($invocant, $owner) = @_;
+ my ($invocant, $owner) = @_;
- $owner || ThrowUserError('component_need_initialowner');
- my $owner_id = Bugzilla::User->check($owner)->id;
- return $owner_id;
+ $owner || ThrowUserError('component_need_initialowner');
+ my $owner_id = Bugzilla::User->check($owner)->id;
+ return $owner_id;
}
sub _check_initialqacontact {
- my ($invocant, $qa_contact) = @_;
-
- my $qa_contact_id;
- if (Bugzilla->params->{'useqacontact'}) {
- $qa_contact_id = Bugzilla::User->check($qa_contact)->id if $qa_contact;
- }
- elsif (ref $invocant) {
- $qa_contact_id = $invocant->{initialqacontact};
- }
- return $qa_contact_id;
+ my ($invocant, $qa_contact) = @_;
+
+ my $qa_contact_id;
+ if (Bugzilla->params->{'useqacontact'}) {
+ $qa_contact_id = Bugzilla::User->check($qa_contact)->id if $qa_contact;
+ }
+ elsif (ref $invocant) {
+ $qa_contact_id = $invocant->{initialqacontact};
+ }
+ return $qa_contact_id;
}
sub _check_product {
- my ($invocant, $product) = @_;
- $product || ThrowCodeError('param_required',
- { function => "$invocant->create", param => 'product' });
- return Bugzilla->user->check_can_admin_product($product->name);
+ my ($invocant, $product) = @_;
+ $product
+ || ThrowCodeError('param_required',
+ {function => "$invocant->create", param => 'product'});
+ return Bugzilla->user->check_can_admin_product($product->name);
}
sub _check_cc_list {
- my ($invocant, $cc_list) = @_;
-
- my %cc_ids;
- foreach my $cc (@$cc_list) {
- my $id = login_to_id($cc, THROW_ERROR);
- $cc_ids{$id} = 1;
- }
- return [keys %cc_ids];
+ my ($invocant, $cc_list) = @_;
+
+ my %cc_ids;
+ foreach my $cc (@$cc_list) {
+ my $id = login_to_id($cc, THROW_ERROR);
+ $cc_ids{$id} = 1;
+ }
+ return [keys %cc_ids];
}
###############################
@@ -248,156 +246,176 @@ sub _check_cc_list {
###############################
sub _update_cc_list {
- my ($self, $cc_list) = @_;
- my $dbh = Bugzilla->dbh;
+ my ($self, $cc_list) = @_;
+ my $dbh = Bugzilla->dbh;
- my $old_cc_list =
- $dbh->selectcol_arrayref('SELECT user_id FROM component_cc
- WHERE component_id = ?', undef, $self->id);
+ my $old_cc_list = $dbh->selectcol_arrayref(
+ 'SELECT user_id FROM component_cc
+ WHERE component_id = ?', undef, $self->id
+ );
- my ($removed, $added) = diff_arrays($old_cc_list, $cc_list);
- my $diff;
- if (scalar @$removed || scalar @$added) {
- $diff = [join(', ', @$removed), join(', ', @$added)];
- }
+ my ($removed, $added) = diff_arrays($old_cc_list, $cc_list);
+ my $diff;
+ if (scalar @$removed || scalar @$added) {
+ $diff = [join(', ', @$removed), join(', ', @$added)];
+ }
- $dbh->do('DELETE FROM component_cc WHERE component_id = ?', undef, $self->id);
+ $dbh->do('DELETE FROM component_cc WHERE component_id = ?', undef, $self->id);
- my $sth = $dbh->prepare('INSERT INTO component_cc
- (user_id, component_id) VALUES (?, ?)');
- $sth->execute($_, $self->id) foreach (@$cc_list);
+ my $sth = $dbh->prepare(
+ 'INSERT INTO component_cc
+ (user_id, component_id) VALUES (?, ?)'
+ );
+ $sth->execute($_, $self->id) foreach (@$cc_list);
- return $diff;
+ return $diff;
}
sub _create_series {
- my $self = shift;
-
- # Insert default charting queries for this product.
- # If they aren't using charting, this won't do any harm.
- my $prodcomp = "&product=" . url_quote($self->product->name) .
- "&component=" . url_quote($self->name);
-
- my $open_query = 'field0-0-0=resolution&type0-0-0=notregexp&value0-0-0=.' .
- $prodcomp;
- my $nonopen_query = 'field0-0-0=resolution&type0-0-0=regexp&value0-0-0=.' .
- $prodcomp;
-
- my @series = ([get_text('series_all_open'), $open_query],
- [get_text('series_all_closed'), $nonopen_query]);
-
- foreach my $sdata (@series) {
- my $series = new Bugzilla::Series(undef, $self->product->name,
- $self->name, $sdata->[0],
- Bugzilla->user->id, 1, $sdata->[1], 1);
- $series->writeToDatabase();
- }
+ my $self = shift;
+
+ # Insert default charting queries for this product.
+ # If they aren't using charting, this won't do any harm.
+ my $prodcomp
+ = "&product="
+ . url_quote($self->product->name)
+ . "&component="
+ . url_quote($self->name);
+
+ my $open_query
+ = 'field0-0-0=resolution&type0-0-0=notregexp&value0-0-0=.' . $prodcomp;
+ my $nonopen_query
+ = 'field0-0-0=resolution&type0-0-0=regexp&value0-0-0=.' . $prodcomp;
+
+ my @series = (
+ [get_text('series_all_open'), $open_query],
+ [get_text('series_all_closed'), $nonopen_query]
+ );
+
+ foreach my $sdata (@series) {
+ my $series
+ = new Bugzilla::Series(undef, $self->product->name, $self->name, $sdata->[0],
+ Bugzilla->user->id, 1, $sdata->[1], 1);
+ $series->writeToDatabase();
+ }
}
-sub set_name { $_[0]->set('name', $_[1]); }
+sub set_name { $_[0]->set('name', $_[1]); }
sub set_description { $_[0]->set('description', $_[1]); }
-sub set_is_active { $_[0]->set('isactive', $_[1]); }
+sub set_is_active { $_[0]->set('isactive', $_[1]); }
+
sub set_default_assignee {
- my ($self, $owner) = @_;
+ my ($self, $owner) = @_;
+
+ $self->set('initialowner', $owner);
- $self->set('initialowner', $owner);
- # Reset the default owner object.
- delete $self->{default_assignee};
+ # Reset the default owner object.
+ delete $self->{default_assignee};
}
+
sub set_default_qa_contact {
- my ($self, $qa_contact) = @_;
+ my ($self, $qa_contact) = @_;
+
+ $self->set('initialqacontact', $qa_contact);
- $self->set('initialqacontact', $qa_contact);
- # Reset the default QA contact object.
- delete $self->{default_qa_contact};
+ # Reset the default QA contact object.
+ delete $self->{default_qa_contact};
}
+
sub set_cc_list {
- my ($self, $cc_list) = @_;
+ my ($self, $cc_list) = @_;
+
+ $self->{cc_ids} = $self->_check_cc_list($cc_list);
- $self->{cc_ids} = $self->_check_cc_list($cc_list);
- # Reset the list of CC user objects.
- delete $self->{initial_cc};
+ # Reset the list of CC user objects.
+ delete $self->{initial_cc};
}
sub bug_count {
- my $self = shift;
- my $dbh = Bugzilla->dbh;
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
- if (!defined $self->{'bug_count'}) {
- $self->{'bug_count'} = $dbh->selectrow_array(q{
+ if (!defined $self->{'bug_count'}) {
+ $self->{'bug_count'} = $dbh->selectrow_array(
+ q{
SELECT COUNT(*) FROM bugs
- WHERE component_id = ?}, undef, $self->id) || 0;
- }
- return $self->{'bug_count'};
+ WHERE component_id = ?}, undef, $self->id
+ ) || 0;
+ }
+ return $self->{'bug_count'};
}
sub bug_ids {
- my $self = shift;
- my $dbh = Bugzilla->dbh;
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
- if (!defined $self->{'bugs_ids'}) {
- $self->{'bugs_ids'} = $dbh->selectcol_arrayref(q{
+ if (!defined $self->{'bugs_ids'}) {
+ $self->{'bugs_ids'} = $dbh->selectcol_arrayref(
+ q{
SELECT bug_id FROM bugs
- WHERE component_id = ?}, undef, $self->id);
- }
- return $self->{'bugs_ids'};
+ WHERE component_id = ?}, undef, $self->id
+ );
+ }
+ return $self->{'bugs_ids'};
}
sub default_assignee {
- my $self = shift;
+ my $self = shift;
- return $self->{'default_assignee'}
- ||= new Bugzilla::User({ id => $self->{'initialowner'}, cache => 1 });
+ return $self->{'default_assignee'}
+ ||= new Bugzilla::User({id => $self->{'initialowner'}, cache => 1});
}
sub default_qa_contact {
- my $self = shift;
+ my $self = shift;
- return unless $self->{'initialqacontact'};
- return $self->{'default_qa_contact'}
- ||= new Bugzilla::User({id => $self->{'initialqacontact'}, cache => 1 });
+ return unless $self->{'initialqacontact'};
+ return $self->{'default_qa_contact'}
+ ||= new Bugzilla::User({id => $self->{'initialqacontact'}, cache => 1});
}
sub flag_types {
- my $self = shift;
-
- if (!defined $self->{'flag_types'}) {
- my $flagtypes = Bugzilla::FlagType::match({ product_id => $self->product_id,
- component_id => $self->id });
-
- $self->{'flag_types'} = {};
- $self->{'flag_types'}->{'bug'} =
- [grep { $_->target_type eq 'bug' } @$flagtypes];
- $self->{'flag_types'}->{'attachment'} =
- [grep { $_->target_type eq 'attachment' } @$flagtypes];
- }
- return $self->{'flag_types'};
+ my $self = shift;
+
+ if (!defined $self->{'flag_types'}) {
+ my $flagtypes = Bugzilla::FlagType::match(
+ {product_id => $self->product_id, component_id => $self->id});
+
+ $self->{'flag_types'} = {};
+ $self->{'flag_types'}->{'bug'}
+ = [grep { $_->target_type eq 'bug' } @$flagtypes];
+ $self->{'flag_types'}->{'attachment'}
+ = [grep { $_->target_type eq 'attachment' } @$flagtypes];
+ }
+ return $self->{'flag_types'};
}
sub initial_cc {
- my $self = shift;
- my $dbh = Bugzilla->dbh;
-
- if (!defined $self->{'initial_cc'}) {
- # If set_cc_list() has been called but data are not yet written
- # into the DB, we want the new values defined by it.
- my $cc_ids = $self->{cc_ids}
- || $dbh->selectcol_arrayref('SELECT user_id FROM component_cc
- WHERE component_id = ?',
- undef, $self->id);
-
- $self->{'initial_cc'} = Bugzilla::User->new_from_list($cc_ids);
- }
- return $self->{'initial_cc'};
+ my $self = shift;
+ my $dbh = Bugzilla->dbh;
+
+ if (!defined $self->{'initial_cc'}) {
+
+ # If set_cc_list() has been called but data are not yet written
+ # into the DB, we want the new values defined by it.
+ my $cc_ids = $self->{cc_ids} || $dbh->selectcol_arrayref(
+ 'SELECT user_id FROM component_cc
+ WHERE component_id = ?', undef,
+ $self->id
+ );
+
+ $self->{'initial_cc'} = Bugzilla::User->new_from_list($cc_ids);
+ }
+ return $self->{'initial_cc'};
}
sub product {
- my $self = shift;
- if (!defined $self->{'product'}) {
- require Bugzilla::Product; # We cannot |use| it.
- $self->{'product'} = new Bugzilla::Product($self->product_id);
- }
- return $self->{'product'};
+ my $self = shift;
+ if (!defined $self->{'product'}) {
+ require Bugzilla::Product; # We cannot |use| it.
+ $self->{'product'} = new Bugzilla::Product($self->product_id);
+ }
+ return $self->{'product'};
}
###############################
@@ -405,8 +423,8 @@ sub product {
###############################
sub description { return $_[0]->{'description'}; }
-sub product_id { return $_[0]->{'product_id'}; }
-sub is_active { return $_[0]->{'isactive'}; }
+sub product_id { return $_[0]->{'product_id'}; }
+sub is_active { return $_[0]->{'isactive'}; }
##############################################
# Implement Bugzilla::Field::ChoiceInterface #
@@ -416,11 +434,11 @@ use constant FIELD_NAME => 'component';
use constant is_default => 0;
sub is_set_on_bug {
- my ($self, $bug) = @_;
- my $value = blessed($bug) ? $bug->component_id : $bug->{component};
- $value = $value->id if blessed($value);
- return 0 unless $value;
- return $value == $self->id ? 1 : 0;
+ my ($self, $bug) = @_;
+ my $value = blessed($bug) ? $bug->component_id : $bug->{component};
+ $value = $value->id if blessed($value);
+ return 0 unless $value;
+ return $value == $self->id ? 1 : 0;
}
###############################