WIP merging create+update
parent
5443865ca5
commit
1656a14cfc
|
@ -1102,21 +1102,25 @@ sub guess_content_type
|
|||
sub get_content_type
|
||||
{
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $ARGS = $cgi->VarHash;
|
||||
|
||||
return 'text/plain' if ($cgi->param('ispatch') ||
|
||||
$cgi->param('text_attachment') !~ /^\s*$/so ||
|
||||
$cgi->param('attachurl'));
|
||||
my $ispatch = $ARGS->{ispatch};
|
||||
if ($ispatch || $ARGS->{text_attachment} !~ /^\s*$/so || $ARGS->{attachurl})
|
||||
{
|
||||
return ('text/plain', $ispatch);
|
||||
}
|
||||
|
||||
my $content_type;
|
||||
if (!defined $cgi->param('contenttypemethod')) {
|
||||
ThrowUserError("missing_content_type_method");
|
||||
if (!defined $ARGS->{contenttypemethod})
|
||||
{
|
||||
ThrowUserError('missing_content_type_method');
|
||||
}
|
||||
elsif ($cgi->param('contenttypemethod') eq 'autodetect') {
|
||||
elsif ($ARGS->{contenttypemethod} eq 'autodetect')
|
||||
{
|
||||
defined $cgi->upload('data') || ThrowUserError('file_not_specified');
|
||||
# The user asked us to auto-detect the content type, so use the type
|
||||
# specified in the HTTP request headers.
|
||||
$content_type =
|
||||
$cgi->uploadInfo($cgi->param('data'))->{'Content-Type'};
|
||||
$content_type = $cgi->uploadInfo($cgi->param('data'))->{'Content-Type'};
|
||||
if (!_legal_content_type($content_type))
|
||||
{
|
||||
$content_type = guess_content_type($cgi->param('data'));
|
||||
|
@ -1129,31 +1133,35 @@ sub get_content_type
|
|||
|
||||
# Set the ispatch flag to 1 if the content type
|
||||
# is text/x-diff or text/x-patch
|
||||
if ($content_type =~ m{text/x-(?:diff|patch)}) {
|
||||
$cgi->param('ispatch', 1);
|
||||
if ($content_type =~ m{text/x-(?:diff|patch)})
|
||||
{
|
||||
$ispatch = 1;
|
||||
$content_type = 'text/plain';
|
||||
}
|
||||
|
||||
# Internet Explorer sends image/x-png for PNG images,
|
||||
# so convert that to image/png to match other browsers.
|
||||
if ($content_type eq 'image/x-png') {
|
||||
elsif ($content_type eq 'image/x-png')
|
||||
{
|
||||
$content_type = 'image/png';
|
||||
}
|
||||
}
|
||||
elsif ($cgi->param('contenttypemethod') eq 'list') {
|
||||
# The user selected a content type from the list, so use their
|
||||
# selection.
|
||||
$content_type = $cgi->param('contenttypeselection');
|
||||
elsif ($ARGS->{contenttypemethod} eq 'list')
|
||||
{
|
||||
# The user selected a content type from the list, so use their selection.
|
||||
$content_type = $ARGS->{contenttypeselection};
|
||||
}
|
||||
elsif ($cgi->param('contenttypemethod') eq 'manual') {
|
||||
elsif ($ARGS->{contenttypemethod} eq 'manual')
|
||||
{
|
||||
# The user entered a content type manually, so use their entry.
|
||||
$content_type = $cgi->param('contenttypeentry');
|
||||
$content_type = $ARGS->{contenttypeentry};
|
||||
}
|
||||
else {
|
||||
ThrowCodeError("illegal_content_type_method",
|
||||
{ contenttypemethod => $cgi->param('contenttypemethod') });
|
||||
else
|
||||
{
|
||||
ThrowCodeError('illegal_content_type_method', {
|
||||
contenttypemethod => $ARGS->{contenttypemethod},
|
||||
});
|
||||
}
|
||||
return $content_type;
|
||||
return ($content_type, $ispatch);
|
||||
}
|
||||
|
||||
# CustIS Bug 68919 - Create multiple attachments to bug
|
||||
|
|
692
Bugzilla/Bug.pm
692
Bugzilla/Bug.pm
|
@ -165,7 +165,7 @@ sub SETTERS
|
|||
bug_status => \&_set_bug_status,
|
||||
resolution => \&_set_resolution,
|
||||
dup_id => \&_set_dup_id,
|
||||
dependencies => _set_dependencies
|
||||
dependencies => \&_set_dependencies,
|
||||
everconfirmed => \&Bugzilla::Object::check_boolean,
|
||||
|
||||
deadline => \&_set_deadline,
|
||||
|
@ -222,10 +222,6 @@ sub DEPENDENCIES
|
|||
{
|
||||
$deps->{$field->name}->{$field->value_field->name} = 1;
|
||||
}
|
||||
if ($field->type == FIELD_TYPE_BUG_ID && $field->add_to_deps)
|
||||
{
|
||||
$deps->{$field->name}->{dependencies} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$cache->{bug_field_deps} = $deps;
|
||||
|
@ -521,226 +517,75 @@ sub match
|
|||
# reasons as C<estimated_time>.
|
||||
sub create
|
||||
{
|
||||
my ($class, $params) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
$dbh->bz_start_transaction();
|
||||
|
||||
# These fields have default values which we can use if they are undefined.
|
||||
$params->{bug_severity} = Bugzilla->params->{defaultseverity}
|
||||
if !defined $params->{bug_severity};
|
||||
$params->{priority} = Bugzilla->params->{defaultpriority}
|
||||
if !defined $params->{priority};
|
||||
$params->{op_sys} = Bugzilla->params->{defaultopsys}
|
||||
if Bugzilla->params->{useopsys} && !defined $params->{op_sys};
|
||||
$params->{rep_platform} = Bugzilla->params->{defaultplatform}
|
||||
if Bugzilla->params->{useplatform} && !defined $params->{rep_platform};
|
||||
# Make sure a comment is always defined.
|
||||
$params->{comment} = '' unless defined $params->{comment};
|
||||
|
||||
$class->check_required_create_fields($params);
|
||||
$params = $class->run_create_validators($params);
|
||||
|
||||
# These are not a fields in the bugs table, so we don't pass them to
|
||||
# insert_create_data.
|
||||
my $cc_ids = delete $params->{cc};
|
||||
my $groups = delete $params->{groups};
|
||||
my $depends_on = delete $params->{dependson};
|
||||
my $blocked = delete $params->{blocked};
|
||||
my ($work_time, $comment, $privacy) = ($params->{work_time}, $params->{comment}, $params->{commentprivacy});
|
||||
delete $params->{work_time};
|
||||
delete $params->{comment};
|
||||
delete $params->{commentprivacy};
|
||||
|
||||
# Set up the keyword cache for bug creation.
|
||||
my $keywords = $params->{keywords};
|
||||
$params->{keywords} = join(', ', sort { lc $a cmp lc $b } map { $_->name } @$keywords);
|
||||
|
||||
# We don't want the bug to appear in the system until it's correctly
|
||||
# protected by groups.
|
||||
my $timestamp = delete $params->{creation_ts};
|
||||
|
||||
my $ms_values = $class->_extract_multi_selects($params);
|
||||
my $bug = $class->insert_create_data($params);
|
||||
|
||||
# CustIS Bug 38616 - CC list restriction
|
||||
# FIXME Use strict_isolation
|
||||
if ($bug->product_obj->cc_group)
|
||||
{
|
||||
$bug->{restricted_cc} = $bug->product_obj->restrict_cc($cc_ids, 'id');
|
||||
}
|
||||
|
||||
# Add the group restrictions
|
||||
my $sth_group = $dbh->prepare('INSERT INTO bug_group_map (bug_id, group_id) VALUES (?, ?)');
|
||||
foreach my $group_id (@$groups)
|
||||
{
|
||||
$sth_group->execute($bug->bug_id, $group_id);
|
||||
}
|
||||
|
||||
$dbh->do('UPDATE bugs SET creation_ts = ? WHERE bug_id = ?', undef, $timestamp, $bug->bug_id);
|
||||
# Update the bug instance as well
|
||||
$bug->{creation_ts} = $timestamp;
|
||||
|
||||
# Add the CCs
|
||||
my $sth_cc = $dbh->prepare('INSERT INTO cc (bug_id, who) VALUES (?,?)');
|
||||
foreach my $user_id (@$cc_ids)
|
||||
{
|
||||
$sth_cc->execute($bug->bug_id, $user_id);
|
||||
}
|
||||
|
||||
# Add keywords
|
||||
my $sth_keyword = $dbh->prepare('INSERT INTO keywords (bug_id, keywordid) VALUES (?, ?)');
|
||||
foreach my $keyword_id (map($_->id, @$keywords))
|
||||
{
|
||||
$sth_keyword->execute($bug->bug_id, $keyword_id);
|
||||
}
|
||||
|
||||
# Set up dependencies (blocked/dependson)
|
||||
my $sth_deps = $dbh->prepare('INSERT INTO dependencies (blocked, dependson) VALUES (?, ?)');
|
||||
my $sth_bug_time = $dbh->prepare('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?');
|
||||
|
||||
foreach my $depends_on_id (@$depends_on)
|
||||
{
|
||||
$sth_deps->execute($bug->bug_id, $depends_on_id);
|
||||
# Log the reverse action on the other bug.
|
||||
LogActivityEntry($depends_on_id, 'blocked', '', $bug->bug_id, $bug->{reporter_id}, $timestamp);
|
||||
$sth_bug_time->execute($timestamp, $depends_on_id);
|
||||
}
|
||||
foreach my $blocked_id (@$blocked)
|
||||
{
|
||||
$sth_deps->execute($blocked_id, $bug->bug_id);
|
||||
# Log the reverse action on the other bug.
|
||||
LogActivityEntry($blocked_id, 'dependson', '', $bug->bug_id, $bug->{reporter_id}, $timestamp);
|
||||
$sth_bug_time->execute($timestamp, $blocked_id);
|
||||
}
|
||||
|
||||
# Insert the values into the multiselect value tables
|
||||
foreach my $field (keys %$ms_values)
|
||||
{
|
||||
$dbh->do("DELETE FROM bug_$field where bug_id = ?", undef, $bug->bug_id);
|
||||
if (@{$ms_values->{$field}})
|
||||
{
|
||||
$dbh->do(
|
||||
"INSERT INTO bug_$field (bug_id, value_id) VALUES ".
|
||||
join(', ', ('(?, ?)') x @{$ms_values->{$field}}),
|
||||
undef, map { ($bug->bug_id, $_) } @{$ms_values->{$field}}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
# And insert the comment. We always insert a comment on bug creation,
|
||||
# but sometimes it's blank.
|
||||
my @columns = qw(bug_id who bug_when thetext work_time);
|
||||
my @values = ($bug->bug_id, $bug->{reporter_id}, $timestamp, $comment, $work_time);
|
||||
# We don't include the "isprivate" column unless it was specified.
|
||||
# This allows it to fall back to its database default.
|
||||
if (defined $privacy)
|
||||
{
|
||||
push @columns, 'isprivate';
|
||||
push @values, $privacy;
|
||||
}
|
||||
my $qmarks = "?," x @columns;
|
||||
chop($qmarks);
|
||||
$dbh->do('INSERT INTO longdescs (' . join(',', @columns) . ") VALUES ($qmarks)", undef, @values);
|
||||
|
||||
Bugzilla::Hook::process('bug_end_of_create', { bug => $bug, timestamp => $timestamp });
|
||||
|
||||
$dbh->bz_commit_transaction();
|
||||
|
||||
# Because MySQL doesn't support transactions on the fulltext table,
|
||||
# we do this after we've committed the transaction. That way we're
|
||||
# sure we're inserting a good Bug ID.
|
||||
$bug->_sync_fulltext('new bug');
|
||||
|
||||
return $bug;
|
||||
die "Unsupported old interface";
|
||||
}
|
||||
|
||||
sub run_create_validators
|
||||
{
|
||||
my $class = shift;
|
||||
my $params = $class->SUPER::run_create_validators(@_);
|
||||
|
||||
my $product = $params->{product};
|
||||
$params->{product_id} = $product->id;
|
||||
|
||||
my $is_open;
|
||||
($params->{bug_status}, $params->{everconfirmed}, $is_open) = $class->_check_bug_status(
|
||||
$params->{bug_status}, $product, $params->{comment}, $params->{assigned_to}
|
||||
);
|
||||
|
||||
if (!$is_open)
|
||||
{
|
||||
# FIXME _check_resolution?
|
||||
my $field = Bugzilla->get_field('resolution');
|
||||
my $type = Bugzilla::Field::Choice->type($field);
|
||||
my $resolution = $type->check({ name => trim($params->{resolution}) });
|
||||
$params->{resolution} = $resolution->id;
|
||||
}
|
||||
|
||||
$params->{target_milestone} = $class->_check_target_milestone($params->{target_milestone}, $product);
|
||||
$params->{version} = $class->_check_version($params->{version}, $product);
|
||||
$params->{keywords} = $class->_check_keywords($params->{keywords}, $params->{keywords_description}, $product);
|
||||
$params->{groups} = $class->_check_groups($product, $params->{groups});
|
||||
|
||||
my $component = $class->_check_component($params->{component}, $product);
|
||||
if ($component)
|
||||
{
|
||||
$params->{component_id} = $component->id;
|
||||
$params->{assigned_to} = $class->_check_assigned_to($params->{assigned_to}, $component);
|
||||
$params->{qa_contact} = $class->_check_qa_contact($params->{qa_contact}, $component);
|
||||
$params->{cc} = $class->_check_cc($component, $params->{cc});
|
||||
}
|
||||
|
||||
# Callers cannot set reporter, creation_ts, or delta_ts.
|
||||
$params->{reporter} = $class->_check_reporter($params->{reporter});
|
||||
$params->{creation_ts} = Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
|
||||
$params->{delta_ts} = $params->{creation_ts};
|
||||
|
||||
if ($params->{estimated_time})
|
||||
{
|
||||
$params->{remaining_time} = $params->{estimated_time};
|
||||
}
|
||||
|
||||
$params->{work_time} = $class->_check_time($params->{work_time}, 'work_time');
|
||||
|
||||
# FIXME strict isolation - это что и вообще работает ли ещё???
|
||||
$class->_check_strict_isolation($params->{cc}, $params->{assigned_to}, $params->{qa_contact}, $product);
|
||||
|
||||
($params->{dependson}, $params->{blocked}) = $class->_check_dependencies($params->{dependson}, $params->{blocked}, $product);
|
||||
|
||||
# You can't set these fields on bug creation (or sometimes ever).
|
||||
delete $params->{bug_id};
|
||||
delete $params->{votes};
|
||||
delete $params->{lastdiffed};
|
||||
|
||||
delete $params->{resolution} if $params->{bug_status} ne 'RESOLVED';
|
||||
|
||||
# Check dependent field values and die on errors
|
||||
check_dependent_fields($dependent_validators, $params);
|
||||
|
||||
# These are converted into IDs
|
||||
delete $params->{product};
|
||||
delete $params->{component};
|
||||
|
||||
# Was used for keywords auto-creation
|
||||
delete $params->{keywords_description};
|
||||
|
||||
Bugzilla::Hook::process('bug_end_of_create_validators', { params => $params });
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
# Check values of the dependent fields
|
||||
# Check values of dependent fields
|
||||
sub check_dependent_fields
|
||||
{
|
||||
my $self = shift;
|
||||
my $incorrect_fields = delete $self->{_incorrect_dependent_values};
|
||||
my $incorrect_fields = {};
|
||||
|
||||
# Run checks in a correct order
|
||||
my %seen = ();
|
||||
my @check = map { field_with_deps($_->name, DEPENDENCIES(), \%seen) } Bugzilla->get_fields({ obsolete => 0 });
|
||||
|
||||
for my $fn (@check)
|
||||
{
|
||||
my $field_obj = Bugzilla->get_field($fn);
|
||||
# Check field visibility
|
||||
if (!$field_obj->check_visibility($self))
|
||||
{
|
||||
# Field is invisible, clear value
|
||||
$self->set($fn, undef);
|
||||
next;
|
||||
}
|
||||
# Optionally add the value of BUG_ID custom field to dependencies (CustIS Bug 73054, Bug 75690)
|
||||
# This allows to see it as a part of the dependency tree
|
||||
if ($field_obj->add_to_deps && $self->{$fn} && $self->{$fn} != $self->id)
|
||||
{
|
||||
my $blk = $field_obj->add_to_deps == BUG_ID_ADD_TO_BLOCKED;
|
||||
my $to = $blk ? 'blocked' : 'dependson';
|
||||
# Get the dependencies from DB
|
||||
if (!$self->{dependency_closure})
|
||||
{
|
||||
$self->{dependency_closure} = ValidateDependencies($self, [ $self->id ], [ $self->id ]);
|
||||
}
|
||||
# Add the bug if it isn't already in the dependency tree
|
||||
if (!$self->{dependency_closure}->{blocked}->{$value} &&
|
||||
!$self->{dependency_closure}->{dependson}->{$value})
|
||||
{
|
||||
push @{$self->{$to}}, $value;
|
||||
}
|
||||
}
|
||||
# Check dependent field values
|
||||
if ($field_obj->value_field_id)
|
||||
{
|
||||
# $self->{_unknown_dependent_values} may contain names of unidentified values
|
||||
my $value_objs = $self->{_unknown_dependent_values}->{$fn} || $self->{$fn.'_obj'};
|
||||
$value_objs = [ $value_objs ] if ref $value_objs ne 'ARRAY';
|
||||
my @bad = grep { !ref $_ || !$_->check_visibility($self) } @$value_objs;
|
||||
if (@bad)
|
||||
{
|
||||
my $n = $field_obj->value_field->name;
|
||||
$incorrect_fields->{$fn} = {
|
||||
field => $field_obj,
|
||||
options => [ map { $_->name } @{ $field_obj->restricted_legal_values($self->$n) } ],
|
||||
values => [ map { ref $_ ? $_ : undef } @bad ],
|
||||
value_names => [ map { ref $_ ? $_ : $_->name } @bad ],
|
||||
controller => $controller,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete $self->{_unknown_dependent_values};
|
||||
|
||||
# When moving bugs between products, verify groups
|
||||
my $verify_bug_groups = undef;
|
||||
if ($self->{_old_self}->product_id != $self->product_id)
|
||||
if ($self->id && $self->{_old_self}->product_id != $self->product_id)
|
||||
{
|
||||
# FIXME Не обращаться к cgi из Bugzilla::Bug!
|
||||
# FIXME Do not call CGI from Bugzilla::Bug!
|
||||
if (!Bugzilla->cgi->param('verify_bug_groups') &&
|
||||
Bugzilla->cgi->param('id'))
|
||||
{
|
||||
|
@ -807,23 +652,58 @@ sub update
|
|||
{
|
||||
my $self = shift;
|
||||
|
||||
my $method = $self->id ? 'update' : 'create';
|
||||
|
||||
# First check dependent field values
|
||||
if ($self->{dependent_validators})
|
||||
{
|
||||
check_dependent_fields($self->{dependent_validators}, $self);
|
||||
}
|
||||
$self->check_dependent_fields;
|
||||
$self->check_strict_isolation;
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $user = Bugzilla->user;
|
||||
# FIXME 'shift ||' is just a temporary hack until all updating happens inside this function
|
||||
my $delta_ts = shift || $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
|
||||
|
||||
Bugzilla::Hook::process('bug_pre_update', { bug => $self });
|
||||
Bugzilla::Hook::process("bug_pre_$method", { bug => $self });
|
||||
|
||||
my ($changes, $old_bug) = $self->SUPER::update(@_);
|
||||
$self->{_old_self} = $old_bug;
|
||||
my $old_bug = $self->{_old_self};
|
||||
my $changes;
|
||||
|
||||
# Transform ID values to names
|
||||
# You can't set these fields by hand
|
||||
$self->{delta_ts} = $delta_ts;
|
||||
delete $params->{votes};
|
||||
delete $params->{lastdiffed};
|
||||
|
||||
if ($self->id)
|
||||
{
|
||||
($changes, $old_bug) = $self->SUPER::update(@_);
|
||||
}
|
||||
else
|
||||
{
|
||||
$self->{bug_severity} = Bugzilla->params->{defaultseverity} if !$self->{bug_severity};
|
||||
$self->{priority} = Bugzilla->params->{defaultpriority} if !$self->{priority};
|
||||
$self->{op_sys} = Bugzilla->params->{defaultopsys} if Bugzilla->params->{useopsys} && !$self->{op_sys};
|
||||
$self->{rep_platform} = Bugzilla->params->{defaultplatform} if Bugzilla->params->{useplatform} && !$self->{rep_platform};
|
||||
$self->{everconfirmed} ||= 0;
|
||||
$self->set('reporter', undef);
|
||||
$self->{creation_ts} = $delta_ts;
|
||||
|
||||
$params->{comment} = '' unless defined $params->{comment};
|
||||
$self->{work_time} = $class->_check_time($params->{work_time}, 'work_time');
|
||||
|
||||
$changes = [];
|
||||
my $row = {};
|
||||
for my $f ($self->DB_COLUMNS)
|
||||
{
|
||||
$row->{$f} = $self->{$f};
|
||||
}
|
||||
$dbh->do(
|
||||
'INSERT INTO '.$self->DB_TABLE.' (' . join(', ', keys %$row) .
|
||||
') VALUES ('.join(', ', ('?') x keys %$row).")", undef, values %$row
|
||||
);
|
||||
$self->{$self->ID_FIELD} = $dbh->bz_last_key($self->DB_TABLE, $self->ID_FIELD);
|
||||
}
|
||||
|
||||
# Transform ID values to names (for the activity log)
|
||||
if ($changes->{product_id})
|
||||
{
|
||||
$changes->{product} = [ $old_bug->product_obj->name, $self->product_obj->name ];
|
||||
|
@ -841,7 +721,6 @@ sub update
|
|||
$changes->{$name}->[0] = $f->new_choice($changes->{$name}->[0])->name if $changes->{$name}->[0];
|
||||
$changes->{$name}->[1] = $f->new_choice($changes->{$name}->[1])->name if $changes->{$name}->[1];
|
||||
}
|
||||
|
||||
# Transform user fields to names + add previous values to CC list
|
||||
foreach my $field (qw(qa_contact assigned_to))
|
||||
{
|
||||
|
@ -862,7 +741,7 @@ sub update
|
|||
}
|
||||
|
||||
# Add/remove CC
|
||||
my @old_cc = map { $_->id } @{$old_bug->cc_users};
|
||||
my @old_cc = $old_bug ? (map { $_->id } @{$old_bug->cc_users}) : ();
|
||||
my @new_cc = @{$self->cc_users};
|
||||
|
||||
# CustIS Bug 38616 - CC list restriction
|
||||
|
@ -889,13 +768,13 @@ sub update
|
|||
{
|
||||
my $removed_users = Bugzilla::User->new_from_list($removed_cc);
|
||||
my $added_users = Bugzilla::User->new_from_list($added_cc);
|
||||
my $removed_names = join(', ', (map {$_->login} @$removed_users));
|
||||
my $added_names = join(', ', (map {$_->login} @$added_users));
|
||||
my $removed_names = join(', ', (map { $_->login } @$removed_users));
|
||||
my $added_names = join(', ', (map { $_->login } @$added_users));
|
||||
$changes->{cc} = [ $removed_names, $added_names ];
|
||||
}
|
||||
|
||||
# Keywords
|
||||
my @old_kw_ids = map { $_->id } @{$old_bug->keyword_objects};
|
||||
my @old_kw_ids = $old_bug ? (map { $_->id } @{$old_bug->keyword_objects}) : ();
|
||||
my @new_kw_ids = map { $_->id } @{$self->keyword_objects};
|
||||
my ($removed_kw, $added_kw) = diff_arrays(\@old_kw_ids, \@new_kw_ids);
|
||||
if (scalar @$removed_kw)
|
||||
|
@ -913,8 +792,8 @@ sub update
|
|||
{
|
||||
my $removed_keywords = Bugzilla::Keyword->new_from_list($removed_kw);
|
||||
my $added_keywords = Bugzilla::Keyword->new_from_list($added_kw);
|
||||
my $removed_names = join(', ', (map {$_->name} @$removed_keywords));
|
||||
my $added_names = join(', ', (map {$_->name} @$added_keywords));
|
||||
my $removed_names = join(', ', (map { $_->name } @$removed_keywords));
|
||||
my $added_names = join(', ', (map { $_->name } @$added_keywords));
|
||||
$changes->{keywords} = [ $removed_names, $added_names ];
|
||||
}
|
||||
|
||||
|
@ -922,7 +801,7 @@ sub update
|
|||
foreach my $pair ([qw(dependson blocked)], [qw(blocked dependson)])
|
||||
{
|
||||
my ($type, $other) = @$pair;
|
||||
my $old = $old_bug->$type;
|
||||
my $old = $old_bug ? $old_bug->$type : [];
|
||||
my $new = $self->$type;
|
||||
|
||||
my ($removed, $added) = diff_arrays($old, $new);
|
||||
|
@ -950,7 +829,7 @@ sub update
|
|||
}
|
||||
|
||||
# Groups
|
||||
my %old_groups = map { $_->id => $_ } @{$old_bug->groups_in};
|
||||
my %old_groups = $old_bug ? (map { $_->id => $_ } @{$old_bug->groups_in}) : ();
|
||||
my %new_groups = map { $_->id => $_ } @{$self->groups_in};
|
||||
my ($removed_gr, $added_gr) = diff_arrays([keys %old_groups], [keys %new_groups]);
|
||||
if (scalar @$removed_gr || scalar @$added_gr)
|
||||
|
@ -1046,11 +925,11 @@ sub update
|
|||
}
|
||||
|
||||
# Insert the values into the multiselect value tables
|
||||
my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT} Bugzilla->active_custom_fields;
|
||||
my @multi_selects = grep { $_->type == FIELD_TYPE_MULTI_SELECT } Bugzilla->active_custom_fields;
|
||||
foreach my $field (@multi_selects)
|
||||
{
|
||||
my $name = $field->name;
|
||||
my ($removed, $added) = diff_arrays($old_bug->$name, $self->$name);
|
||||
my ($removed, $added) = diff_arrays($old_bug ? $old_bug->$name : [], $self->$name);
|
||||
if (scalar @$removed || scalar @$added)
|
||||
{
|
||||
$changes->{$name} = [
|
||||
|
@ -1070,7 +949,7 @@ sub update
|
|||
}
|
||||
|
||||
# See Also
|
||||
my ($removed_see, $added_see) = diff_arrays($old_bug->see_also, $self->see_also);
|
||||
my ($removed_see, $added_see) = diff_arrays($old_bug ? $old_bug->see_also : [], $self->see_also);
|
||||
if (scalar @$removed_see)
|
||||
{
|
||||
$dbh->do(
|
||||
|
@ -1099,7 +978,7 @@ sub update
|
|||
}
|
||||
|
||||
# Check if we have to update the duplicates table and the other bug.
|
||||
my ($old_dup, $cur_dup) = ($old_bug->dup_id || 0, $self->dup_id || 0);
|
||||
my ($old_dup, $cur_dup) = ($old_bug ? $old_bug->dup_id || 0 : 0, $self->dup_id || 0);
|
||||
if ($old_dup != $cur_dup)
|
||||
{
|
||||
$dbh->do("DELETE FROM duplicates WHERE dupe = ?", undef, $self->id);
|
||||
|
@ -1114,14 +993,7 @@ sub update
|
|||
$changes->{dup_id} = [$old_dup || undef, $cur_dup || undef];
|
||||
}
|
||||
|
||||
# If any change occurred, refresh the timestamp of the bug.
|
||||
if (scalar(keys %$changes) || $self->{added_comments})
|
||||
{
|
||||
$dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?', undef, ($delta_ts, $self->id));
|
||||
$self->{delta_ts} = $delta_ts;
|
||||
}
|
||||
|
||||
Bugzilla::Hook::process('bug_end_of_update', {
|
||||
Bugzilla::Hook::process("bug_end_of_$method", {
|
||||
bug => $self,
|
||||
timestamp => $delta_ts,
|
||||
changes => $changes,
|
||||
|
@ -1135,7 +1007,7 @@ sub update
|
|||
if ($self->{added_comments} || $changes->{short_desc} ||
|
||||
$self->{comment_isprivate} || $self->{edited_comments})
|
||||
{
|
||||
$self->_sync_fulltext();
|
||||
$self->_sync_fulltext($method eq 'create');
|
||||
}
|
||||
|
||||
# Remove obsolete internal variables.
|
||||
|
@ -1150,23 +1022,69 @@ sub update
|
|||
return $changes;
|
||||
}
|
||||
|
||||
# Used by create().
|
||||
# We need to handle multi-select fields differently than normal fields,
|
||||
# because they're arrays and don't go into the bugs table.
|
||||
sub _extract_multi_selects
|
||||
# Check strict isolation for $self:
|
||||
# Throw an error when trying to modify bug in such way that someone of
|
||||
# its reporter/assignee/QA/CC are not permitted to see its product.
|
||||
# We always check all users, so in theory some bugs may become "blocked"
|
||||
# for further modifications if their reporter can't see the product.
|
||||
# It is intended to work like that.
|
||||
sub check_strict_isolation
|
||||
{
|
||||
my ($invocant, $params) = @_;
|
||||
my %ms_values;
|
||||
foreach my $field (Bugzilla->get_fields({ type => FIELD_TYPE_MULTI_SELECT }))
|
||||
my $self = shift;
|
||||
|
||||
# CustIS Bug 38616 - CC list restriction
|
||||
my $ccg = $self->product_obj->cc_group;
|
||||
if ($ccg)
|
||||
{
|
||||
my $name = $field->name;
|
||||
if (exists $params->{$name})
|
||||
for (qw(assigned_to reporter qa_contact))
|
||||
{
|
||||
my $array = delete($params->{$name}) || [];
|
||||
$ms_values{$name} = $array;
|
||||
if ($self->$_ && !$self->$_->in_group($ccg))
|
||||
{
|
||||
ThrowUserError('cc_group_restriction', { user => $self->$_->login });
|
||||
}
|
||||
}
|
||||
}
|
||||
return \%ms_values;
|
||||
|
||||
return unless Bugzilla->params->{strict_isolation};
|
||||
|
||||
my $old = $self->{_old_self};
|
||||
|
||||
my %related_users;
|
||||
$related_users{$_->id} = $_ for @{$self->cc_users};
|
||||
|
||||
for (qw(assigned_to reporter qa_contact))
|
||||
{
|
||||
if ($self->$_)
|
||||
{
|
||||
$related_users->{$self->$_->id} ||= $self->$_;
|
||||
}
|
||||
}
|
||||
|
||||
my @blocked_users;
|
||||
my $product = $self->product_obj;
|
||||
foreach my $related_user (values %related_users)
|
||||
{
|
||||
if (!$related_user->can_see_product($product->name))
|
||||
{
|
||||
push @blocked_users, $related_user->login;
|
||||
}
|
||||
}
|
||||
if (@blocked_users)
|
||||
{
|
||||
my %vars = (
|
||||
users => \@blocked_users,
|
||||
product => $product->name,
|
||||
);
|
||||
if ($self->id)
|
||||
{
|
||||
$vars{bug_id} = $self->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$vars{new} = 1;
|
||||
}
|
||||
ThrowUserError("invalid_user_group", \%vars);
|
||||
}
|
||||
}
|
||||
|
||||
# Should be called any time you update short_desc or change a comment.
|
||||
|
@ -1289,7 +1207,7 @@ sub set
|
|||
my ($self, $field, $value) = @_;
|
||||
if (my $setter = SETTERS->{$field})
|
||||
{
|
||||
if (!$self->{_dirty})
|
||||
if ($self->id && !$self->{_dirty})
|
||||
{
|
||||
$self->{_old_self} = bless { %$self }, 'Bugzilla::Bug';
|
||||
$self->{_dirty} = 1;
|
||||
|
@ -1364,13 +1282,12 @@ sub _set_assigned_to
|
|||
my $user = Bugzilla->user;
|
||||
my $component = $self->component;
|
||||
|
||||
my $id;
|
||||
my $is_new = !$self->id;
|
||||
if ($is_new && (!$user->in_group('editbugs', $component->product_id) || !$assignee))
|
||||
{
|
||||
# If this is a new bug, you can only set the assignee if you have editbugs.
|
||||
# If you didn't specify the assignee, we use the default assignee.
|
||||
$id = $component->default_assignee->id;
|
||||
$self->{assigned_to_obj} = $component->default_assignee;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1381,20 +1298,10 @@ sub _set_assigned_to
|
|||
ThrowUserError('reassign_to_empty') if !$is_new && !$assignee;
|
||||
$assignee = Bugzilla::User->check($assignee);
|
||||
}
|
||||
$id = $assignee->id;
|
||||
$invocant->_check_strict_isolation_for_user($assignee);
|
||||
# CustIS Bug 38616 - CC list restriction
|
||||
# FIXME use strict_isolation
|
||||
my ($ccg) = $component->product->cc_group;
|
||||
if ($ccg && !$assignee->in_group($ccg))
|
||||
{
|
||||
ThrowUserError('cc_group_restriction', { user => $assignee->login });
|
||||
}
|
||||
$self->{assigned_to_obj} = $assignee;
|
||||
}
|
||||
|
||||
delete $self->{assigned_to_obj};
|
||||
|
||||
return $id;
|
||||
return $self->{assigned_to_obj}->id;
|
||||
}
|
||||
|
||||
sub _set_bug_file_loc
|
||||
|
@ -1550,6 +1457,7 @@ sub _set_cc
|
|||
return [ keys %cc_ids ];
|
||||
}
|
||||
|
||||
# $bug->set('add_comment', { thetext => '', work_time => 0, isprivate => 0, type => CMT_WORKTIME });
|
||||
sub _set_add_comment
|
||||
{
|
||||
my ($self, $params) = @_;
|
||||
|
@ -1623,7 +1531,12 @@ sub _set_component
|
|||
my ($self, $name) = @_;
|
||||
$name = trim($name);
|
||||
$name || ThrowUserError('require_component');
|
||||
my $obj = Bugzilla::Component->check({ product => $self->product_obj, name => $name });
|
||||
my $obj = Bugzilla::Component->new({ product => $self->product_obj, name => $name });
|
||||
if (!$obj)
|
||||
{
|
||||
$self->{_unknown_dependent_values}->{component} = [ $name ];
|
||||
return undef;
|
||||
}
|
||||
if ($self->component->id != $obj->id)
|
||||
{
|
||||
$self->{component_id} = $obj->id;
|
||||
|
@ -1996,6 +1909,7 @@ sub _set_qa_contact
|
|||
if (!Bugzilla->user->in_group('editbugs', $component->product_id) || !$qa_contact)
|
||||
{
|
||||
$id = $component->default_qa_contact->id;
|
||||
$self->{qa_contact_obj} = $component->default_qa_contact;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2005,21 +1919,14 @@ sub _set_qa_contact
|
|||
{
|
||||
$qa_contact = Bugzilla::User->check($qa_contact) if !ref $qa_contact;
|
||||
$id = $qa_contact->id;
|
||||
$invocant->_check_strict_isolation_for_user($qa_contact);
|
||||
my $ccg = $self->product_obj->cc_group;
|
||||
if ($ccg && !$qa_contact->in_group($ccg))
|
||||
{
|
||||
ThrowUserError('cc_group_restriction', { user => $qa_contact->login });
|
||||
}
|
||||
$self->{qa_contact_obj} = $qa_contact;
|
||||
}
|
||||
|
||||
delete $self->{qa_contact_obj};
|
||||
|
||||
# "0" always means "undef", for QA Contact.
|
||||
return $id || undef;
|
||||
}
|
||||
|
||||
sub _set_reporter # FIXME????????????????
|
||||
sub _set_reporter
|
||||
{
|
||||
my $self = shift;
|
||||
my $reporter;
|
||||
|
@ -2147,89 +2054,6 @@ sub _set_status_whiteboard
|
|||
return defined $value ? $value : '';
|
||||
}
|
||||
|
||||
# Unlike other checkers, this one doesn't return anything.
|
||||
sub _check_strict_isolation
|
||||
{
|
||||
my ($invocant, $ccs, $assignee, $qa_contact, $product) = @_;
|
||||
return unless Bugzilla->params->{strict_isolation};
|
||||
|
||||
if (ref $invocant)
|
||||
{
|
||||
my $original = $invocant->new($invocant->id);
|
||||
|
||||
# We only check people if they've been added. This way, if
|
||||
# strict_isolation is turned on when there are invalid users
|
||||
# on bugs, people can still add comments and so on.
|
||||
my @old_cc = map { $_->id } @{$original->cc_users};
|
||||
my @new_cc = map { $_->id } @{$invocant->cc_users};
|
||||
my ($removed, $added) = diff_arrays(\@old_cc, \@new_cc);
|
||||
$ccs = Bugzilla::User->new_from_list($added);
|
||||
|
||||
$assignee = $invocant->assigned_to if $invocant->assigned_to->id != $original->assigned_to->id;
|
||||
if ($invocant->qa_contact &&
|
||||
(!$original->qa_contact || $invocant->qa_contact->id != $original->qa_contact->id))
|
||||
{
|
||||
$qa_contact = $invocant->qa_contact;
|
||||
}
|
||||
$product = $invocant->product_obj;
|
||||
}
|
||||
|
||||
my @related_users = @$ccs;
|
||||
push @related_users, $assignee if $assignee;
|
||||
|
||||
if (Bugzilla->params->{useqacontact} && $qa_contact)
|
||||
{
|
||||
push @related_users, $qa_contact;
|
||||
}
|
||||
|
||||
@related_users = @{Bugzilla::User->new_from_list(\@related_users)} if !ref $invocant;
|
||||
|
||||
# For each unique user in @related_users...(assignee and qa_contact
|
||||
# could be duplicates of users in the CC list)
|
||||
my %unique_users = map {$_->id => $_} @related_users;
|
||||
my @blocked_users;
|
||||
foreach my $id (keys %unique_users)
|
||||
{
|
||||
my $related_user = $unique_users{$id};
|
||||
if (!$related_user->can_edit_product($product->id) ||
|
||||
!$related_user->can_see_product($product->name))
|
||||
{
|
||||
push @blocked_users, $related_user->login;
|
||||
}
|
||||
}
|
||||
if (scalar @blocked_users)
|
||||
{
|
||||
my %vars = (
|
||||
users => \@blocked_users,
|
||||
product => $product->name
|
||||
);
|
||||
if (ref $invocant)
|
||||
{
|
||||
$vars{bug_id} = $invocant->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$vars{new} = 1;
|
||||
}
|
||||
ThrowUserError("invalid_user_group", \%vars);
|
||||
}
|
||||
}
|
||||
|
||||
# This is used by various set_ checkers, to make their code simpler.
|
||||
sub _check_strict_isolation_for_user
|
||||
{
|
||||
my ($self, $user) = @_;
|
||||
return unless Bugzilla->params->{strict_isolation};
|
||||
if (!$user->can_edit_bug($self))
|
||||
{
|
||||
ThrowUserError('invalid_user_group', {
|
||||
users => $user->login,
|
||||
product => $self->product,
|
||||
bug_id => $self->id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sub _set_target_milestone
|
||||
{
|
||||
my ($self, $target) = @_;
|
||||
|
@ -2244,10 +2068,16 @@ sub _set_target_milestone
|
|||
}
|
||||
if ((!defined $target || !length $target) && Bugzilla->get_field('target_milestone')->nullable)
|
||||
{
|
||||
return undef;
|
||||
$self->{target_milestone_obj} = undef;
|
||||
return $self->{target_milestone} = undef;
|
||||
}
|
||||
# FIXME use set_select_field
|
||||
my $object = Bugzilla::Milestone->check({ product => $product, name => $target });
|
||||
my $object = Bugzilla::Milestone->new({ product => $product, name => $target });
|
||||
if (!$object)
|
||||
{
|
||||
$self->{_unknown_dependent_values}->{target_milestone} = [ $target ];
|
||||
return undef;
|
||||
}
|
||||
return $object->id;
|
||||
}
|
||||
|
||||
|
@ -2257,10 +2087,16 @@ sub _set_version
|
|||
$version = trim($version);
|
||||
if ((!defined $version || !length $version) && Bugzilla->get_field('version')->nullable)
|
||||
{
|
||||
return undef;
|
||||
$self->{version_obj} = undef;
|
||||
return $self->{version} = undef;
|
||||
}
|
||||
# FIXME use set_select_field
|
||||
my $object = Bugzilla::Version->check({ product => $self->product_obj, name => $version });
|
||||
my $object = Bugzilla::Version->new({ product => $self->product_obj, name => $version });
|
||||
if (!$object)
|
||||
{
|
||||
$self->{_unknown_dependent_values}->{version} = [ $version ];
|
||||
return undef;
|
||||
}
|
||||
return $object->id;
|
||||
}
|
||||
|
||||
|
@ -2275,12 +2111,26 @@ sub _set_time
|
|||
|
||||
sub _set_estimated_time
|
||||
{
|
||||
return $_[0]->_set_time($_[1], 'estimated_time');
|
||||
my ($self, $time, $field) = @_;
|
||||
my $v = $self->_set_time($time, $field);
|
||||
if (!$self->id && !$self->remaining_time && $v)
|
||||
{
|
||||
# Set remaining_time == estimated_time on new bugs if it was empty
|
||||
$self->{remaining_time} = $v;
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
|
||||
sub _set_remaining_time
|
||||
{
|
||||
return $_[0]->_set_time($_[1], 'remaining_time');
|
||||
my ($self, $time, $field) = @_;
|
||||
my $v = $self->_set_time($time, $field);
|
||||
if (!$self->id && !$v && $self->estimated_time)
|
||||
{
|
||||
# Set remaining_time == estimated_time on new bugs if it was empty
|
||||
$v = $self->estimated_time;
|
||||
}
|
||||
return $v;
|
||||
}
|
||||
|
||||
# Custom Field Validators/Setters
|
||||
|
@ -2289,17 +2139,11 @@ sub _set_datetime_field
|
|||
{
|
||||
my ($self, $date_time, $field) = @_;
|
||||
|
||||
# Check field visibility
|
||||
if (!Bugzilla->get_field($field)->check_visibility($self))
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
|
||||
# Empty datetimes are empty strings or strings only containing
|
||||
# 0's, whitespace, and punctuation.
|
||||
if ($date_time =~ /^[\s0[:punct:]]*$/)
|
||||
{
|
||||
return undef;
|
||||
return $self->{$field} = undef;
|
||||
}
|
||||
|
||||
$date_time = trim($date_time);
|
||||
|
@ -2318,7 +2162,7 @@ sub _set_datetime_field
|
|||
sub _set_default_field
|
||||
{
|
||||
my ($self, $value, $field) = @_;
|
||||
if (!Bugzilla->get_field($field)->check_visibility($self) || !defined($value))
|
||||
if (!defined($value))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
@ -2328,10 +2172,6 @@ sub _set_default_field
|
|||
sub _set_numeric_field
|
||||
{
|
||||
my ($self, $text, $field) = @_;
|
||||
if (!Bugzilla->get_field($field)->check_visibility($self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
($text) = $text =~ /^(-?\d+(\.\d+)?)$/so;
|
||||
return $text || 0;
|
||||
}
|
||||
|
@ -2339,10 +2179,6 @@ sub _set_numeric_field
|
|||
sub _set_freetext_field
|
||||
{
|
||||
my ($self, $text) = @_;
|
||||
if (!Bugzilla->get_field($field)->check_visibility($self))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
$text = (defined $text) ? trim($text) : '';
|
||||
if (length($text) > MAX_FREETEXT_LENGTH)
|
||||
{
|
||||
|
@ -2367,40 +2203,21 @@ sub _set_multi_select_field
|
|||
$values = [ split ',', $values ];
|
||||
}
|
||||
|
||||
# Check field visibility
|
||||
my $field_obj = Bugzilla->get_field($field);
|
||||
if (!$values || !@$values || !$field_obj->check_visibility($self))
|
||||
if (!$values || !@$values)
|
||||
{
|
||||
$self->{$field.'_obj'} = [];
|
||||
return [];
|
||||
}
|
||||
|
||||
my $field_obj = Bugzilla->get_field($field);
|
||||
my $t = Bugzilla::Field::Choice->type($field_obj);
|
||||
my $value_objs = $t->match({ name => $values });
|
||||
my $h = { map { lc($_->name) => $_ } @$value_objs };
|
||||
for my $value (@$values)
|
||||
my @bad = grep { !$h->{lc $_} } @$values;
|
||||
if (@bad)
|
||||
{
|
||||
if (!$h->{lc $value})
|
||||
{
|
||||
ThrowUserError('object_does_not_exist', { class => $t, name => $value });
|
||||
}
|
||||
}
|
||||
|
||||
if ($field_obj->value_field_id)
|
||||
{
|
||||
# Check dependent field values
|
||||
my @bad = grep { !$_->check_visibility($self) } @$value_objs;
|
||||
if (@bad)
|
||||
{
|
||||
my $n = $field_obj->value_field->name;
|
||||
$self->{_incorrect_dependent_values}->{$field} = {
|
||||
field => $field_obj,
|
||||
options => [ map { $_->name } @{ $field->restricted_legal_values($self->$n) } ],
|
||||
values => \@bad,
|
||||
value_names => [ map { $_->name } @bad ],
|
||||
controller => $controller,
|
||||
};
|
||||
}
|
||||
$self->{_unknown_dependent_values}->{$field} = \@bad;
|
||||
return undef;
|
||||
}
|
||||
|
||||
$self->{$field.'_obj'} = $value_objs;
|
||||
|
@ -2411,26 +2228,19 @@ sub _set_select_field
|
|||
{
|
||||
my ($self, $value, $field) = @_;
|
||||
my $field_obj = Bugzilla->get_field($field);
|
||||
# Check field visibility and check for an empty value
|
||||
if ((!defined $value || !length $value) && $field_obj->nullable ||
|
||||
!$field_obj->check_visibility($self))
|
||||
# Allow empty values, but only for nullable or invisible fields
|
||||
if ((!defined $value || !length $value) &&
|
||||
($field_obj->nullable || !$field_obj->check_visibility($self)))
|
||||
{
|
||||
$self->{$field.'_obj'} = undef;
|
||||
return undef;
|
||||
return $self->{$field} = undef;
|
||||
}
|
||||
my $t = Bugzilla::Field::Choice->type($field_obj);
|
||||
my $value_obj = $t->check({ name => $value });
|
||||
if ($field_obj->value_field_id && !$value_obj->check_visibility($self))
|
||||
my $value_obj = $t->new({ name => $value });
|
||||
if (!$value_obj)
|
||||
{
|
||||
# Check dependent field values
|
||||
my $n = $field_obj->value_field->name;
|
||||
$self->{_incorrect_dependent_values}->{$field} = {
|
||||
field => $field_obj,
|
||||
options => [ map { $_->name } @{ $field->restricted_legal_values($self->$n) } ],
|
||||
values => [ $value_obj ],
|
||||
value_names => [ $value ],
|
||||
controller => $controller,
|
||||
};
|
||||
$self->{_unknown_dependent_values}->{$field} = [ $value ];
|
||||
return undef;
|
||||
}
|
||||
$self->{$field.'_obj'} = $value_obj;
|
||||
return $value_obj->id;
|
||||
|
@ -2439,14 +2249,7 @@ sub _set_select_field
|
|||
sub _set_bugid_field
|
||||
{
|
||||
my ($self, $value, $field) = @_;
|
||||
return undef if !$value;
|
||||
|
||||
# Check field visibility
|
||||
my $field_obj = Bugzilla->get_field($field);
|
||||
if (!$values || !@$values || !$field_obj->check_visibility($self))
|
||||
{
|
||||
return undef;
|
||||
}
|
||||
return $self->{$field} = undef if !$value;
|
||||
|
||||
my $r;
|
||||
if ($self->{$field} eq $value)
|
||||
|
@ -2459,20 +2262,6 @@ sub _set_bugid_field
|
|||
$r = Bugzilla::Bug->check($value, $field)->id;
|
||||
}
|
||||
|
||||
# Optionally add the value to dependencies (CustIS Bug 73054, Bug 75690)
|
||||
# This allows to see BUG_ID custom field values as the part of dependency tree
|
||||
if ($field_obj->add_to_deps && $r != $self->id)
|
||||
{
|
||||
my $blk = $field_obj->add_to_deps == BUG_ID_ADD_TO_BLOCKED;
|
||||
my $to = $blk ? 'blocked' : 'dependson';
|
||||
# Add the bug if it isn't already in dependency tree
|
||||
if (!$self->{dependency_closure}->{blocked}->{$value} &&
|
||||
!$self->{dependency_closure}->{dependson}->{$value})
|
||||
{
|
||||
push @{$self->{$to}}, $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
@ -2618,7 +2407,6 @@ sub add_cc
|
|||
my ($self, $user_or_name) = @_;
|
||||
return if !$user_or_name;
|
||||
my $user = ref $user_or_name ? $user_or_name : Bugzilla::User->check($user_or_name);
|
||||
$self->_check_strict_isolation_for_user($user);
|
||||
my $cc_users = $self->cc_users;
|
||||
push @$cc_users, $user if !grep { $_->id == $user->id } @$cc_users;
|
||||
}
|
||||
|
@ -2633,7 +2421,7 @@ sub remove_cc
|
|||
@$cc_users = grep { $_->id != $user->id } @$cc_users;
|
||||
}
|
||||
|
||||
# Edit comment checker
|
||||
# Edit a comment
|
||||
sub edit_comment
|
||||
{
|
||||
my ($self, $comment_id, $comment) = @_;
|
||||
|
|
|
@ -568,6 +568,7 @@ sub cookie
|
|||
sub VarHash
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->{_VarHash} if $self->{_VarHash};
|
||||
my ($force_array) = @_;
|
||||
my $args = { %{ $self->Vars } };
|
||||
my $filtered = {};
|
||||
|
@ -575,18 +576,18 @@ sub VarHash
|
|||
{
|
||||
if ($key =~ /\[\]$/so)
|
||||
{
|
||||
$filtered->{substr $key, 0, -2} = ref $args->{$key} ? $args->{$key} : [ $args->{$key} ];
|
||||
$filtered->{substr $key, 0, -2} = ref $args->{$key} eq 'ARRAY' ? $args->{$key} : [ $args->{$key} ];
|
||||
}
|
||||
elsif ($force_array->{$key})
|
||||
{
|
||||
$filtered->{$key} = ref $args->{$key} ? $args->{$key} : [ $args->{$key} ];
|
||||
$filtered->{$key} = ref $args->{$key} eq 'ARRAY' ? $args->{$key} : [ $args->{$key} ];
|
||||
}
|
||||
else
|
||||
{
|
||||
$filtered->{$key} = ref $args->{$key} ? $args->{$key}->[-1] : $args->{$key};
|
||||
$filtered->{$key} = ref $args->{$key} eq 'ARRAY' ? $args->{$key}->[-1] : $args->{$key};
|
||||
}
|
||||
}
|
||||
return $filtered;
|
||||
return $self->{_VarHash} = $filtered;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -379,12 +379,6 @@ sub update
|
|||
|
||||
$dbh->do("UPDATE $table SET $columns WHERE $id_field = ?", undef, @values, $self->id) if @values;
|
||||
|
||||
Bugzilla::Hook::process('object_end_of_update', {
|
||||
object => $self,
|
||||
old_object => $old_self,
|
||||
changes => \%changes,
|
||||
});
|
||||
|
||||
$dbh->bz_commit_transaction();
|
||||
|
||||
if (wantarray)
|
||||
|
@ -398,7 +392,6 @@ sub update
|
|||
sub remove_from_db
|
||||
{
|
||||
my $self = shift;
|
||||
Bugzilla::Hook::process('object_before_delete', { object => $self });
|
||||
my $table = $self->DB_TABLE;
|
||||
my $id_field = $self->ID_FIELD;
|
||||
Bugzilla->dbh->do("DELETE FROM $table WHERE $id_field = ?", undef, $self->id);
|
||||
|
@ -448,10 +441,6 @@ sub check_required_create_fields
|
|||
{
|
||||
my ($class, $params) = @_;
|
||||
|
||||
# This hook happens here so that even subclasses that don't call
|
||||
# SUPER::create are still affected by the hook.
|
||||
Bugzilla::Hook::process('object_before_create', { class => $class, params => $params });
|
||||
|
||||
foreach my $field ($class->REQUIRED_CREATE_FIELDS)
|
||||
{
|
||||
ThrowCodeError('param_required', { function => "${class}->create", param => $field })
|
||||
|
@ -466,8 +455,6 @@ sub run_create_validators
|
|||
my $validators = $class->VALIDATORS;
|
||||
my %field_values = %$params;
|
||||
|
||||
local $Bugzilla::Object::CREATE_PARAMS = \%field_values;
|
||||
|
||||
# We do the sort just to make sure that validation always
|
||||
# happens in a consistent order.
|
||||
foreach my $field (sort keys %field_values)
|
||||
|
@ -482,9 +469,6 @@ sub run_create_validators
|
|||
trick_taint($field_values{$field}) if defined $field_values{$field} && !ref $field_values{$field};
|
||||
}
|
||||
|
||||
Bugzilla::Hook::process('object_end_of_create_validators',
|
||||
{ class => $class, params => \%field_values });
|
||||
|
||||
return \%field_values;
|
||||
}
|
||||
|
||||
|
@ -517,7 +501,6 @@ sub insert_create_data
|
|||
|
||||
my $object = $class->new($id);
|
||||
|
||||
Bugzilla::Hook::process('object_end_of_create', { class => $class, object => $object });
|
||||
return $object;
|
||||
}
|
||||
|
||||
|
|
|
@ -511,7 +511,7 @@ sub insert
|
|||
}
|
||||
|
||||
# Must be called before create() as it may alter $cgi->param('ispatch').
|
||||
my $content_type = Bugzilla::Attachment::get_content_type();
|
||||
my ($content_type, $ispatch) = Bugzilla::Attachment::get_content_type();
|
||||
|
||||
my $data = scalar $cgi->param('attachurl') || $cgi->upload('data');
|
||||
my $filename = '';
|
||||
|
@ -537,7 +537,7 @@ sub insert
|
|||
data => $data,
|
||||
description => scalar $cgi->param('description'),
|
||||
filename => $filename,
|
||||
ispatch => scalar $cgi->param('ispatch'),
|
||||
ispatch => $ispatch,
|
||||
isprivate => scalar $cgi->param('isprivate'),
|
||||
isurl => scalar $cgi->param('attachurl'),
|
||||
mimetype => $content_type,
|
||||
|
|
179
post_bug.cgi
179
post_bug.cgi
|
@ -1,6 +1,4 @@
|
|||
#!/usr/bin/perl -wT
|
||||
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy of
|
||||
|
@ -50,6 +48,14 @@ my $cgi = Bugzilla->cgi;
|
|||
my $dbh = Bugzilla->dbh;
|
||||
my $template = Bugzilla->template;
|
||||
my $vars = {};
|
||||
my $ARGS = $cgi->VarHash({
|
||||
cc => 1,
|
||||
(map { ($_->name => 1) } Bugzilla->get_fields({
|
||||
type => FIELD_TYPE_MULTI_SELECT,
|
||||
enter_bug => 1,
|
||||
obsolete => 0,
|
||||
})),
|
||||
});
|
||||
|
||||
######################################################################
|
||||
# Main Script
|
||||
|
@ -59,7 +65,7 @@ my $vars = {};
|
|||
print $cgi->redirect(correct_urlbase() . 'enter_bug.cgi') unless $cgi->param();
|
||||
|
||||
# Detect if the user already used the same form to submit a bug
|
||||
my $token = trim($cgi->param('token'));
|
||||
my $token = trim($ARGS->{token});
|
||||
check_token_data($token, qr/^createbug:/s, 'enter_bug.cgi');
|
||||
|
||||
my (undef, undef, $old_bug_id) = Bugzilla::Token::GetTokenData($token);
|
||||
|
@ -67,55 +73,56 @@ $old_bug_id =~ s/^createbug://;
|
|||
if ($old_bug_id)
|
||||
{
|
||||
$vars->{bugid} = $old_bug_id;
|
||||
$vars->{allow_override} = defined $cgi->param('ignore_token') ? 0 : 1;
|
||||
$vars->{allow_override} = defined $ARGS->{ignore_token} ? 0 : 1;
|
||||
$vars->{new_token} = issue_session_token('createbug:');
|
||||
|
||||
$template->process("bug/create/confirm-create-dupe.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
|| ThrowTemplateError($template->error);
|
||||
exit;
|
||||
}
|
||||
|
||||
# do a match on the fields if applicable
|
||||
Bugzilla::User::match_field ({
|
||||
'cc' => { 'type' => 'multi' },
|
||||
'assigned_to' => { 'type' => 'single' },
|
||||
'qa_contact' => { 'type' => 'single' },
|
||||
Bugzilla::User::match_field({
|
||||
cc => { type => 'multi' },
|
||||
assigned_to => { type => 'single' },
|
||||
qa_contact => { type => 'single' },
|
||||
});
|
||||
|
||||
if (defined $cgi->param('maketemplate')) {
|
||||
$vars->{'url'} = $cgi->canonicalise_query('token', 'cloned_bug_id', 'cloned_comment');
|
||||
$vars->{'short_desc'} = $cgi->param('short_desc');
|
||||
if (defined $ARGS->{maketemplate})
|
||||
{
|
||||
$vars->{url} = $cgi->canonicalise_query('token', 'cloned_bug_id', 'cloned_comment');
|
||||
$vars->{short_desc} = $ARGS->{short_desc};
|
||||
|
||||
$template->process("bug/create/make-template.html.tmpl", $vars)
|
||||
|| ThrowTemplateError($template->error());
|
||||
|| ThrowTemplateError($template->error);
|
||||
exit;
|
||||
}
|
||||
|
||||
umask 0;
|
||||
umask 0; # FIXME WTF???
|
||||
|
||||
# Group Validation
|
||||
my @selected_groups;
|
||||
foreach my $group (grep(/^bit-\d+$/, $cgi->param())) {
|
||||
$group =~ /^bit-(\d+)$/;
|
||||
push(@selected_groups, $1);
|
||||
for (keys %$ARGS)
|
||||
{
|
||||
if (/^bit-(\d+)$/)
|
||||
{
|
||||
push @selected_groups, $1;
|
||||
}
|
||||
}
|
||||
|
||||
# The format of the initial comment can be structured by adding fields to the
|
||||
# enter_bug template and then referencing them in the comment template.
|
||||
my $comment;
|
||||
my $format = $template->get_format("bug/create/comment",
|
||||
scalar($cgi->param('format')), "txt");
|
||||
$template->process($format->{'template'}, $vars, \$comment)
|
||||
|| ThrowTemplateError($template->error());
|
||||
my $format = $template->get_format('bug/create/comment', $ARGS->{format}, 'txt');
|
||||
$template->process($format->{template}, $vars, \$comment)
|
||||
|| ThrowTemplateError($template->error);
|
||||
|
||||
# Include custom fields editable on bug creation.
|
||||
my @custom_bug_fields = grep {$_->type != FIELD_TYPE_MULTI_SELECT && $_->enter_bug}
|
||||
Bugzilla->active_custom_fields;
|
||||
my @custom_bug_fields = grep { $_->enter_bug } Bugzilla->active_custom_fields;
|
||||
|
||||
# Undefined custom fields are ignored to ensure they will get their default
|
||||
# value (e.g. "---" for custom single select fields).
|
||||
my @bug_fields = grep { defined $cgi->param($_->name) } @custom_bug_fields;
|
||||
@bug_fields = map { $_->name } @bug_fields;
|
||||
my @bug_fields = grep { defined $ARGS->{$_} } map { $_->name } @custom_bug_fields;
|
||||
|
||||
push(@bug_fields, qw(
|
||||
product
|
||||
|
@ -147,54 +154,49 @@ push(@bug_fields, qw(
|
|||
push @bug_fields, 'op_sys' if Bugzilla->params->{useopsys};
|
||||
push @bug_fields, 'rep_platform' if Bugzilla->params->{useplatform};
|
||||
my %bug_params;
|
||||
foreach my $field (@bug_fields) {
|
||||
$bug_params{$field} = $cgi->param($field);
|
||||
foreach my $field (@bug_fields)
|
||||
{
|
||||
$bug_params{$field} = $ARGS->{$field};
|
||||
}
|
||||
$bug_params{'cc'} = [$cgi->param('cc')];
|
||||
$bug_params{'groups'} = \@selected_groups;
|
||||
$bug_params{'comment'} = $comment;
|
||||
$bug_params{cc} = $ARGS->{cc};
|
||||
$bug_params{groups} = \@selected_groups;
|
||||
$bug_params{comment} = $comment;
|
||||
|
||||
if ($user->is_timetracker)
|
||||
{
|
||||
$bug_params{'work_time'} = $cgi->param('work_time') || 0;
|
||||
$bug_params{work_time} = $ARGS->{work_time} || 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$bug_params{'work_time'} = 0;
|
||||
$bug_params{work_time} = 0;
|
||||
}
|
||||
|
||||
my @multi_selects = Bugzilla->get_fields({
|
||||
custom => 1,
|
||||
type => FIELD_TYPE_MULTI_SELECT,
|
||||
enter_bug => 1,
|
||||
obsolete => 0,
|
||||
});
|
||||
|
||||
foreach my $field (@multi_selects)
|
||||
{
|
||||
$bug_params{$field->name} = [$cgi->param($field->name)];
|
||||
}
|
||||
|
||||
# CustIS Bug 63152 - Duplicated bugs on attachment create errors
|
||||
# Wrap bug creation in a transaction, so attachment create errors
|
||||
# don't lead to duplicated bugs. Also it allows many ugly hacks
|
||||
# to be removed from Bugzilla::Bug. (CustIS Bug 63152)
|
||||
Bugzilla->dbh->bz_start_transaction;
|
||||
|
||||
my $bug = Bugzilla::Bug->create(\%bug_params);
|
||||
my $bug = new Bugzilla::Bug;
|
||||
|
||||
$bug->set...
|
||||
dependencies => { dependson, blocked }
|
||||
comment => { thetext, work_time, isprivate, type }
|
||||
keywords => { keywords, descriptions }
|
||||
|
||||
# Get the bug ID back.
|
||||
my $id = $bug->bug_id;
|
||||
|
||||
# We do this directly from the DB because $bug->creation_ts has the seconds
|
||||
# formatted out of it (which should be fixed some day).
|
||||
my $timestamp = $dbh->selectrow_array(
|
||||
'SELECT creation_ts FROM bugs WHERE bug_id = ?', undef, $id);
|
||||
my $timestamp = $bug->creation_ts;
|
||||
|
||||
# Set Version cookie, but only if the user actually selected
|
||||
# a version on the page.
|
||||
if (defined $cgi->param('version') && length $cgi->param('version'))
|
||||
if (defined $ARGS->{version} && $ARGS->{version} ne '')
|
||||
{
|
||||
$cgi->send_cookie(-name => "VERSION-" . $bug->product,
|
||||
-value => $bug->version,
|
||||
-expires => "Fri, 01-Jan-2038 00:00:00 GMT");
|
||||
$cgi->send_cookie(
|
||||
-name => "VERSION-" . $bug->product,
|
||||
-value => $bug->version,
|
||||
-expires => "Fri, 01-Jan-2038 00:00:00 GMT"
|
||||
);
|
||||
}
|
||||
|
||||
# We don't have to check if the user can see the bug, because a user filing
|
||||
|
@ -203,7 +205,7 @@ if (defined $cgi->param('version') && length $cgi->param('version'))
|
|||
|
||||
# Add an attachment if requested.
|
||||
my $is_multiple = 0;
|
||||
for (keys %{$cgi->Vars})
|
||||
for (keys %$ARGS)
|
||||
{
|
||||
if (/^attachmulti_(.*)_([^_]*)$/so)
|
||||
{
|
||||
|
@ -219,45 +221,47 @@ if ($is_multiple)
|
|||
my $send_attrs = {};
|
||||
Bugzilla::Attachment::add_multiple($bug, $cgi, $send_attrs);
|
||||
}
|
||||
elsif (defined($cgi->upload('data')) || $cgi->param('attachurl') ||
|
||||
$cgi->param('text_attachment') || $cgi->param('base64_content'))
|
||||
elsif (defined($cgi->upload('data')) || $ARGS->{attachurl} ||
|
||||
$ARGS->{text_attachment} || $ARGS->{base64_content})
|
||||
{
|
||||
$cgi->param('isprivate', $cgi->param('commentprivacy'));
|
||||
$ARGS->{isprivate} = $ARGS->{commentprivacy};
|
||||
|
||||
# Must be called before create() as it may alter $cgi->param('ispatch').
|
||||
my $content_type = Bugzilla::Attachment::get_content_type();
|
||||
# Must be called before create() as it may alter $ARGS->{ispatch}.
|
||||
my ($content_type, $ispatch) = Bugzilla::Attachment::get_content_type();
|
||||
my $attachment;
|
||||
|
||||
# If the attachment cannot be successfully added to the bug,
|
||||
# we notify the user, but we don't interrupt the bug creation process.
|
||||
my $error_mode_cache = Bugzilla->error_mode;
|
||||
Bugzilla->error_mode(ERROR_MODE_DIE);
|
||||
eval {
|
||||
my $data = scalar $cgi->param('attachurl') || $cgi->upload('data');
|
||||
eval
|
||||
{
|
||||
my $data = $ARGS->{attachurl} || $ARGS->{data};
|
||||
my $filename = '';
|
||||
$filename = scalar $cgi->upload('data') || $cgi->param('filename') unless $cgi->param('attachurl');
|
||||
if (scalar $cgi->param('text_attachment') !~ /^\s*$/so)
|
||||
$filename = scalar($cgi->upload('data')) || $ARGS->{filename} unless $ARGS->{attachurl};
|
||||
if ($ARGS->{text_attachment} !~ /^\s*$/so)
|
||||
{
|
||||
$data = $cgi->param('text_attachment');
|
||||
$filename = $cgi->param('description');
|
||||
$data = $ARGS->{text_attachment};
|
||||
$filename = $ARGS->{description};
|
||||
}
|
||||
$attachment = Bugzilla::Attachment->create(
|
||||
{bug => $bug,
|
||||
creation_ts => $timestamp,
|
||||
data => $data,
|
||||
description => scalar $cgi->param('description'),
|
||||
filename => $filename,
|
||||
ispatch => scalar $cgi->param('ispatch'),
|
||||
isprivate => scalar $cgi->param('isprivate'),
|
||||
isurl => scalar $cgi->param('attachurl'),
|
||||
mimetype => $content_type,
|
||||
store_in_file => scalar $cgi->param('bigfile'),
|
||||
base64_content => scalar $cgi->param('base64_content'),
|
||||
});
|
||||
$attachment = Bugzilla::Attachment->create({
|
||||
bug => $bug,
|
||||
creation_ts => $timestamp,
|
||||
data => $data,
|
||||
description => $ARGS->{description},
|
||||
filename => $filename,
|
||||
ispatch => $ispatch,
|
||||
isprivate => $ARGS->{isprivate},
|
||||
isurl => $ARGS->{attachurl},
|
||||
mimetype => $content_type,
|
||||
store_in_file => $ARGS->{bigfile},
|
||||
base64_content => $ARGS->{base64_content},
|
||||
});
|
||||
};
|
||||
Bugzilla->error_mode($error_mode_cache);
|
||||
|
||||
if ($attachment) {
|
||||
if ($attachment)
|
||||
{
|
||||
# Set attachment flags.
|
||||
my ($flags, $new_flags) = Bugzilla::Flag->extract_flags_from_cgi(
|
||||
$bug, $attachment, $vars
|
||||
|
@ -268,8 +272,9 @@ elsif (defined($cgi->upload('data')) || $cgi->param('attachurl') ||
|
|||
$comment->set_type(CMT_ATTACHMENT_CREATED, $attachment->id);
|
||||
$comment->update();
|
||||
}
|
||||
else {
|
||||
$vars->{'message'} = 'attachment_creation_failed';
|
||||
else
|
||||
{
|
||||
$vars->{message} = 'attachment_creation_failed';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,21 +283,17 @@ my ($flags, $new_flags) = Bugzilla::Flag->extract_flags_from_cgi($bug, undef, $v
|
|||
$bug->set_flags($flags, $new_flags);
|
||||
$bug->update($timestamp);
|
||||
|
||||
$vars->{'id'} = $id;
|
||||
$vars->{'bug'} = $bug;
|
||||
$vars->{id} = $id;
|
||||
$vars->{bug} = $bug;
|
||||
|
||||
# CustIS Bug 63152 - Duplicated bugs on attachment create errors
|
||||
Bugzilla->dbh->bz_commit_transaction;
|
||||
|
||||
Bugzilla::Hook::process('post_bug_after_creation', { vars => $vars });
|
||||
|
||||
ThrowCodeError("bug_error", { bug => $bug }) if $bug->error;
|
||||
|
||||
if ($token)
|
||||
{
|
||||
trick_taint($token);
|
||||
$dbh->do('UPDATE tokens SET eventdata = ? WHERE token = ?', undef,
|
||||
("createbug:$id", $token));
|
||||
$dbh->do('UPDATE tokens SET eventdata = ? WHERE token = ?', undef, "createbug:$id", $token);
|
||||
}
|
||||
|
||||
my $bug_sent = { bug_id => $id, type => 'created', mailrecipients => { changer => $user->login } };
|
||||
|
|
|
@ -283,7 +283,7 @@ if (defined $ARGS->{product})
|
|||
foreach my $b (@bug_objects)
|
||||
{
|
||||
$b->{_other_bugs} = \@bug_objects;
|
||||
my $changed = $b->set_product($ARGS->{product});
|
||||
my $changed = $b->set('product', $ARGS->{product});
|
||||
$product_change ||= $changed;
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ if ($ARGS->{id})
|
|||
|
||||
if ($ARGS->{id} && (defined $ARGS->{dependson} || defined $ARGS->{blocked}))
|
||||
{
|
||||
$first_bug->set_dependencies($ARGS->{dependson}, $ARGS->{blocked});
|
||||
$first_bug->set('dependencies', { dependson => $ARGS->{dependson}, blocked => $ARGS->{blocked} });
|
||||
}
|
||||
elsif (defined $ARGS->{dependson} || defined $ARGS->{blocked})
|
||||
{
|
||||
|
@ -348,7 +348,7 @@ elsif (defined $ARGS->{dependson} || defined $ARGS->{blocked})
|
|||
}
|
||||
}
|
||||
}
|
||||
$bug->set_dependencies([ keys %{$temp_deps{dependson}} ], [ keys %{$temp_deps{blocked}} ]);
|
||||
$bug->set('dependencies', { dependson => [ keys %{$temp_deps{dependson}} ], blocked => [ keys %{$temp_deps{blocked}} ] });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,14 +371,12 @@ if ($ARGS->{keywords})
|
|||
# them twice.
|
||||
my @custom_fields = Bugzilla->active_custom_fields;
|
||||
|
||||
my $methods = { component => 'set_component' };
|
||||
$methods->{assigned_to} = 'set_assigned_to' if !$ARGS->{set_default_assignee};
|
||||
$methods->{qa_contact} = 'set_qa_contact' if !$ARGS->{set_default_qa_contact};
|
||||
|
||||
my @set_fields = qw(
|
||||
deadline remaining_time estimated_time alias op_sys rep_platform bug_severity
|
||||
component deadline remaining_time estimated_time alias op_sys rep_platform bug_severity
|
||||
priority status_whiteboard short_desc target_milestone bug_file_loc version
|
||||
);
|
||||
push @set_fields, 'assigned_to' if !$ARGS->{set_default_assignee};
|
||||
push @set_fields, 'qa_contact' if !$ARGS->{set_default_qa_contact};
|
||||
|
||||
foreach my $b (@bug_objects)
|
||||
{
|
||||
|
@ -397,14 +395,7 @@ foreach my $b (@bug_objects)
|
|||
if (defined $ARGS->{$field_name} ||
|
||||
defined $ARGS->{product} && $field_name =~ /^(component|target_milestone|version)$/)
|
||||
{
|
||||
if (my $m = $methods->{$field_name})
|
||||
{
|
||||
$b->$m($ARGS->{$field_name} || '');
|
||||
}
|
||||
else
|
||||
{
|
||||
$b->set($field_name, $ARGS->{$field_name} || '');
|
||||
}
|
||||
$b->set($field_name, $ARGS->{$field_name} || '');
|
||||
}
|
||||
}
|
||||
$b->reset_assigned_to if $ARGS->{set_default_assignee};
|
||||
|
@ -426,7 +417,7 @@ foreach my $b (@bug_objects)
|
|||
my $fname = $field->name;
|
||||
if (defined $ARGS->{$fname} || defined $ARGS->{"defined_$fname"}) # FIXME array[] for multiselects
|
||||
{
|
||||
$b->set_custom_field($field, $ARGS->{$fname});
|
||||
$b->set($fname, $ARGS->{$fname});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue