2008-12-15 15:53:33 +03:00
|
|
|
#!/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
|
|
|
|
# the License at http://www.mozilla.org/MPL/
|
|
|
|
#
|
|
|
|
# Software distributed under the License is distributed on an "AS
|
|
|
|
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
# implied. See the License for the specific language governing
|
|
|
|
# rights and limitations under the License.
|
|
|
|
#
|
|
|
|
# The Original Code is the Bugzilla Bug Tracking System.
|
|
|
|
#
|
|
|
|
# The Initial Developer of the Original Code is Netscape Communications
|
|
|
|
# Corporation. Portions created by Netscape are
|
|
|
|
# Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
# Rights Reserved.
|
|
|
|
#
|
|
|
|
# Contributor(s): Terry Weissman <terry@mozilla.org>
|
|
|
|
# Dan Mosedale <dmose@mozilla.org>
|
|
|
|
# Dave Miller <justdave@syndicomm.com>
|
|
|
|
# Christopher Aillon <christopher@aillon.com>
|
|
|
|
# Myk Melez <myk@mozilla.org>
|
|
|
|
# Jeff Hedlund <jeff.hedlund@matrixsi.com>
|
|
|
|
# Frédéric Buclin <LpSolit@gmail.com>
|
|
|
|
# Lance Larsh <lance.larsh@oracle.com>
|
|
|
|
# Akamai Technologies <bugzilla-dev@akamai.com>
|
|
|
|
# Max Kanat-Alexander <mkanat@bugzilla.org>
|
|
|
|
|
|
|
|
# Implementation notes for this file:
|
|
|
|
#
|
|
|
|
# 1) the 'id' form parameter is validated early on, and if it is not a valid
|
|
|
|
# bugid an error will be reported, so it is OK for later code to simply check
|
|
|
|
# for a defined form 'id' value, and it can assume a valid bugid.
|
|
|
|
#
|
2014-03-08 02:36:38 +04:00
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# 2) If the 'id' form parameter is not defined (after the initial validation),
|
|
|
|
# then we are processing multiple bugs, and @idlist will contain the ids.
|
|
|
|
#
|
|
|
|
# 3) If we are processing just the one id, then it is stored in @idlist for
|
|
|
|
# later processing.
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
use lib qw(. lib);
|
|
|
|
|
|
|
|
use Bugzilla;
|
|
|
|
use Bugzilla::Constants;
|
|
|
|
use Bugzilla::Bug;
|
|
|
|
use Bugzilla::BugMail;
|
|
|
|
use Bugzilla::Mailer;
|
|
|
|
use Bugzilla::User;
|
|
|
|
use Bugzilla::Util;
|
|
|
|
use Bugzilla::Error;
|
|
|
|
use Bugzilla::Field;
|
|
|
|
use Bugzilla::Product;
|
|
|
|
use Bugzilla::Component;
|
|
|
|
use Bugzilla::Keyword;
|
|
|
|
use Bugzilla::Flag;
|
|
|
|
use Bugzilla::Status;
|
2009-02-09 18:57:34 +03:00
|
|
|
use Bugzilla::Token;
|
2008-12-15 15:53:33 +03:00
|
|
|
|
2010-10-22 20:57:14 +04:00
|
|
|
use Checkers;
|
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
use Storable qw(dclone);
|
|
|
|
|
|
|
|
my $user = Bugzilla->login(LOGIN_REQUIRED);
|
|
|
|
|
|
|
|
my $cgi = Bugzilla->cgi;
|
|
|
|
my $dbh = Bugzilla->dbh;
|
|
|
|
my $template = Bugzilla->template;
|
|
|
|
my $vars = {};
|
2011-10-04 18:01:24 +04:00
|
|
|
my $ARGS = { %{ $cgi->Vars } };
|
2014-03-31 17:22:50 +04:00
|
|
|
#my $ARGS = $cgi->VarHash; # FIXME (see lines with "FIXME array[]")
|
2008-12-15 15:53:33 +03:00
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# Begin Data/Security Validation
|
|
|
|
######################################################################
|
|
|
|
|
2010-09-08 18:52:08 +04:00
|
|
|
$dbh->bz_start_transaction();
|
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# Create a list of objects for all bugs being modified in this request.
|
2010-09-08 18:52:08 +04:00
|
|
|
# <vitalif@mail.ru> Use SELECT ... FOR UPDATE to lock these bugs
|
2008-12-15 15:53:33 +03:00
|
|
|
my @bug_objects;
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{id})
|
|
|
|
{
|
2014-03-31 17:22:50 +04:00
|
|
|
($ARGS->{id}) = @{$ARGS->{id}} if ref $ARGS->{id}; # FIXME array[]
|
2014-03-08 02:36:38 +04:00
|
|
|
my $bug = Bugzilla::Bug->check({ id => $ARGS->{id}, for_update => 1 });
|
|
|
|
$ARGS->{id} = $bug->id;
|
|
|
|
push @bug_objects, $bug;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
foreach my $i (keys %$ARGS)
|
|
|
|
{
|
|
|
|
if ($i =~ /^id_([1-9][0-9]*)/)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
my $id = $1;
|
2014-03-08 02:36:38 +04:00
|
|
|
push @bug_objects, Bugzilla::Bug->check({ id => $id, for_update => 1 });
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Make sure there are bugs to process.
|
|
|
|
scalar(@bug_objects) || ThrowUserError("no_bugs_chosen", {action => 'modify'});
|
|
|
|
|
|
|
|
my $first_bug = $bug_objects[0]; # Used when we're only updating a single bug.
|
|
|
|
|
|
|
|
# Delete any parameter set to 'dontchange'.
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{dontchange})
|
|
|
|
{
|
|
|
|
foreach my $name (keys %$ARGS)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
next if $name eq 'dontchange'; # But don't delete dontchange itself!
|
|
|
|
# Skip ones we've already deleted (such as "defined_$name").
|
2014-03-08 02:36:38 +04:00
|
|
|
next if !defined $ARGS->{$name};
|
2014-03-31 17:22:50 +04:00
|
|
|
if ($ARGS->{$name} eq $ARGS->{dontchange} ||
|
|
|
|
ref $ARGS->{$name} && @{$ARGS->{$name}} == 1 && $ARGS->{$name}->[0] eq $ARGS->{dontchange})
|
2014-03-08 02:36:38 +04:00
|
|
|
{
|
2011-10-04 19:11:48 +04:00
|
|
|
delete $ARGS->{$name};
|
|
|
|
delete $ARGS->{"defined_$name"};
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# do a match on the fields if applicable
|
2010-05-15 00:02:34 +04:00
|
|
|
Bugzilla::User::match_field({
|
2014-03-08 02:36:38 +04:00
|
|
|
'qa_contact' => { type => 'single' },
|
2014-03-31 17:22:50 +04:00
|
|
|
'newcc' => { type => 'multi' }, # FIXME array[]
|
|
|
|
'masscc' => { type => 'multi' }, # FIXME array[]
|
2014-03-08 02:36:38 +04:00
|
|
|
'assigned_to' => { type => 'single' },
|
2008-12-15 15:53:33 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
# Check for a mid-air collision. Currently this only works when updating
|
|
|
|
# an individual bug.
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{delta_ts})
|
2008-12-15 15:53:33 +03:00
|
|
|
{
|
2014-03-08 02:36:38 +04:00
|
|
|
my $delta_ts_z = datetime_from($ARGS->{delta_ts});
|
2010-09-08 18:52:08 +04:00
|
|
|
my $first_delta_tz_z = datetime_from($first_bug->delta_ts);
|
2010-06-04 23:09:20 +04:00
|
|
|
if ($first_delta_tz_z ne $delta_ts_z)
|
|
|
|
{
|
2014-03-08 02:36:38 +04:00
|
|
|
($vars->{operations}) = Bugzilla::Bug::GetBugActivity($first_bug->id, undef, $ARGS->{delta_ts});
|
2008-12-15 15:53:33 +03:00
|
|
|
|
2012-01-12 19:04:04 +04:00
|
|
|
# CustIS Bug 56327 - Change only fields the user wanted to change
|
2010-06-04 23:09:20 +04:00
|
|
|
for my $op (@{$vars->{operations}})
|
2009-10-30 20:02:38 +03:00
|
|
|
{
|
2010-06-04 23:09:20 +04:00
|
|
|
for (@{$op->{changes}})
|
2009-10-30 20:02:38 +03:00
|
|
|
{
|
2012-01-12 19:32:34 +04:00
|
|
|
# FIXME similar detection is needed for other multi-selects
|
|
|
|
if ($_->{fieldname} eq 'dependson' || $_->{fieldname} eq 'blocked')
|
|
|
|
{
|
|
|
|
# Calculate old value from current value and activity log
|
|
|
|
my $cur = $_->{fieldname};
|
|
|
|
$cur = { map { $_ => 1 } @{ $first_bug->$cur() } };
|
|
|
|
my $new = join ', ', keys %$cur;
|
|
|
|
delete $cur->{$_} for split /[\s,]*,[\s,]*/, $_->{added};
|
|
|
|
$cur->{$_} = 1 for split /[\s,]*,[\s,]*/, $_->{removed};
|
|
|
|
# Compare the old value with submitted one
|
|
|
|
my $equal = 1;
|
2014-03-08 02:36:38 +04:00
|
|
|
for (split /[\s,]*,[\s,]*/, $ARGS->{$_->{fieldname}})
|
2012-01-12 19:32:34 +04:00
|
|
|
{
|
|
|
|
if (!$cur->{$_})
|
|
|
|
{
|
|
|
|
$equal = 0;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
delete $cur->{$_};
|
|
|
|
}
|
|
|
|
$equal = 0 if %$cur;
|
|
|
|
# If equal to old value -> change to the new value
|
2014-03-08 02:36:38 +04:00
|
|
|
$ARGS->{$_->{fieldname}} = $new if $equal;
|
2012-01-12 19:32:34 +04:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
elsif ($ARGS->{$_->{fieldname}} eq $_->{removed})
|
2010-06-04 23:09:20 +04:00
|
|
|
{
|
|
|
|
# If equal to old value -> change to the new value
|
2014-03-08 02:36:38 +04:00
|
|
|
$ARGS->{$_->{fieldname}} = $_->{added};
|
2010-06-04 23:09:20 +04:00
|
|
|
}
|
2009-10-30 20:02:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
$vars->{title_tag} = "mid_air";
|
2010-06-04 23:09:20 +04:00
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
ThrowCodeError('undefined_field', { field => 'longdesclength' }) if !$ARGS->{longdesclength};
|
2010-05-15 00:02:34 +04:00
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
$vars->{start_at} = $ARGS->{longdesclength};
|
2010-05-15 00:02:34 +04:00
|
|
|
# Always sort midair collision comments oldest to newest,
|
|
|
|
# regardless of the user's personal preference.
|
2014-03-08 02:36:38 +04:00
|
|
|
$vars->{comments} = $first_bug->comments({ order => "oldest_to_newest", start_at => $vars->{start_at} });
|
|
|
|
$vars->{bug} = $first_bug;
|
|
|
|
$vars->{ARGS} = $ARGS;
|
2010-05-15 00:02:34 +04:00
|
|
|
|
|
|
|
# The token contains the old delta_ts. We need a new one.
|
2014-03-08 02:36:38 +04:00
|
|
|
$ARGS->{token} = issue_hash_token([ $first_bug->id, $first_bug->delta_ts ]);
|
2010-05-15 00:02:34 +04:00
|
|
|
# Warn the user about the mid-air collision and ask them what to do.
|
|
|
|
$template->process("bug/process/midair.html.tmpl", $vars)
|
2014-03-08 02:36:38 +04:00
|
|
|
|| ThrowTemplateError($template->error());
|
2010-05-15 00:02:34 +04:00
|
|
|
exit;
|
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
2013-09-26 12:04:33 +04:00
|
|
|
my %edit_comment;
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $key (keys %$ARGS)
|
|
|
|
{
|
|
|
|
if ($key =~ /edit_comment\[(.*)\]$/)
|
|
|
|
{
|
|
|
|
my $comment_id = $1;
|
|
|
|
trick_taint($ARGS->{$key});
|
|
|
|
$edit_comment{$comment_id} = $ARGS->{$key};
|
2013-09-26 12:04:33 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-09 18:57:34 +03:00
|
|
|
# We couldn't do this check earlier as we first had to validate bug IDs
|
|
|
|
# and display the mid-air collision page if delta_ts changed.
|
|
|
|
# If we do a mass-change, we use session tokens.
|
2014-03-08 02:36:38 +04:00
|
|
|
my $token = $ARGS->{token};
|
2009-02-09 18:57:34 +03:00
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{id})
|
|
|
|
{
|
|
|
|
check_hash_token($token, [ $first_bug->id, $first_bug->delta_ts ]);
|
2009-02-09 18:57:34 +03:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
else
|
|
|
|
{
|
2009-02-09 18:57:34 +03:00
|
|
|
check_token_data($token, 'buglist_mass_change', 'query.cgi');
|
|
|
|
}
|
|
|
|
|
|
|
|
######################################################################
|
|
|
|
# End Data/Security Validation
|
|
|
|
######################################################################
|
|
|
|
|
2008-12-23 17:19:11 +03:00
|
|
|
$vars->{title_tag} = "bug_processed";
|
2014-03-08 02:36:38 +04:00
|
|
|
$vars->{commentsilent} = $ARGS->{commentsilent};
|
2008-12-15 15:53:33 +03:00
|
|
|
|
2010-05-15 00:02:34 +04:00
|
|
|
my $action;
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{id})
|
|
|
|
{
|
|
|
|
$action = Bugzilla->user->settings->{post_bug_submit_action}->{value};
|
|
|
|
if ($action eq 'next_bug')
|
|
|
|
{
|
2010-05-15 00:02:34 +04:00
|
|
|
my @bug_list;
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($cgi->cookie("BUGLIST")) # TODO
|
|
|
|
{
|
|
|
|
@bug_list = split /:/, $cgi->cookie("BUGLIST");
|
2010-05-15 00:02:34 +04:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
my $cur = lsearch(\@bug_list, $ARGS->{id});
|
|
|
|
if ($cur >= 0 && $cur < $#bug_list)
|
|
|
|
{
|
2010-05-15 00:02:34 +04:00
|
|
|
my $next_bug_id = $bug_list[$cur + 1];
|
|
|
|
detaint_natural($next_bug_id);
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($next_bug_id && $user->can_see_bug($next_bug_id))
|
|
|
|
{
|
2010-05-15 00:02:34 +04:00
|
|
|
# We create an object here so that send_results can use it
|
|
|
|
# when displaying the header.
|
2014-03-08 02:36:38 +04:00
|
|
|
$vars->{bug} = new Bugzilla::Bug($next_bug_id);
|
2010-05-15 00:02:34 +04:00
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
# Include both action = 'same_bug' and 'nothing'.
|
2014-03-08 02:36:38 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
$vars->{bug} = $first_bug;
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
else
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# param('id') is not defined when changing multiple bugs at once.
|
|
|
|
$action = 'nothing';
|
|
|
|
}
|
|
|
|
|
|
|
|
# For each bug, we have to check if the user can edit the bug the product
|
|
|
|
# is currently in, before we allow them to change anything.
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $bug (@bug_objects)
|
|
|
|
{
|
2009-11-27 15:59:45 +03:00
|
|
|
Bugzilla->user->can_edit_bug($bug, THROW_ERROR);
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
2010-03-09 20:12:04 +03:00
|
|
|
# For security purposes, and because lots of other checks depend on it,
|
|
|
|
# we set the product first before anything else.
|
|
|
|
my $product_change; # Used only for strict_isolation checks, right now.
|
2014-03-08 02:36:38 +04:00
|
|
|
if (defined $ARGS->{product})
|
|
|
|
{
|
|
|
|
foreach my $b (@bug_objects)
|
|
|
|
{
|
2010-11-24 20:22:45 +03:00
|
|
|
$b->{_other_bugs} = \@bug_objects;
|
2014-03-08 02:36:38 +04:00
|
|
|
my $changed = $b->set_product($ARGS->{product});
|
2010-03-09 20:12:04 +03:00
|
|
|
$product_change ||= $changed;
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2010-03-09 20:12:04 +03:00
|
|
|
}
|
2009-12-02 16:39:36 +03:00
|
|
|
|
2010-03-09 20:12:04 +03:00
|
|
|
# strict_isolation checks mean that we should set the groups
|
|
|
|
# immediately after changing the product.
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $b (@bug_objects)
|
|
|
|
{
|
|
|
|
foreach my $group (@{$b->product_obj->groups_valid})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
my $gid = $group->id;
|
2014-03-08 02:36:38 +04:00
|
|
|
if (defined $ARGS->{"bit-$gid"} || defined $ARGS->{"defined_bit-$gid"})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# Check ! first to avoid having to check defined below.
|
2014-03-08 02:36:38 +04:00
|
|
|
if (!$ARGS->{"bit-$gid"})
|
|
|
|
{
|
2010-03-09 20:12:04 +03:00
|
|
|
$b->remove_group($gid);
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
# "== 1" is important because mass-change uses -1 to mean
|
|
|
|
# "don't change this restriction"
|
2014-03-08 02:36:38 +04:00
|
|
|
elsif ($ARGS->{"bit-$gid"} == 1)
|
|
|
|
{
|
2010-03-09 20:12:04 +03:00
|
|
|
$b->add_group($gid);
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-06 19:18:55 +04:00
|
|
|
Bugzilla::Hook::process('process_bug-after_move', { bug_objects => \@bug_objects, vars => $vars });
|
|
|
|
|
2010-05-15 00:02:34 +04:00
|
|
|
# Flags should be set AFTER the bug has been moved into another product/component.
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{id})
|
|
|
|
{
|
2010-05-15 00:02:34 +04:00
|
|
|
my ($flags, $new_flags) = Bugzilla::Flag->extract_flags_from_cgi($first_bug, undef, $vars);
|
|
|
|
$first_bug->set_flags($flags, $new_flags);
|
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{id} && (defined $ARGS->{dependson} || defined $ARGS->{blocked}))
|
2008-12-15 15:53:33 +03:00
|
|
|
{
|
2014-03-08 02:36:38 +04:00
|
|
|
$first_bug->set_dependencies($ARGS->{dependson}, $ARGS->{blocked});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
elsif (defined $ARGS->{dependson} || defined $ARGS->{blocked})
|
|
|
|
{
|
|
|
|
foreach my $bug (@bug_objects)
|
|
|
|
{
|
2009-07-29 15:21:49 +04:00
|
|
|
my %temp_deps;
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $type (qw(dependson blocked))
|
|
|
|
{
|
2009-07-29 15:21:49 +04:00
|
|
|
$temp_deps{$type} = { map { $_ => 1 } @{$bug->$type} };
|
2014-03-08 02:36:38 +04:00
|
|
|
if (defined $ARGS->{$type} && $ARGS->{$type.'_action'} =~ /^(add|remove)$/)
|
|
|
|
{
|
|
|
|
foreach my $id (split /[,\s]+/, $ARGS->{$type})
|
|
|
|
{
|
|
|
|
if ($ARGS->{$type.'_action'} eq 'remove')
|
|
|
|
{
|
2009-07-29 15:21:49 +04:00
|
|
|
delete $temp_deps{$type}{$id};
|
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
else
|
|
|
|
{
|
2009-07-29 15:21:49 +04:00
|
|
|
$temp_deps{$type}{$id} = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
$bug->set_dependencies([ keys %{$temp_deps{dependson}} ], [ keys %{$temp_deps{blocked}} ]);
|
2009-07-29 15:21:49 +04:00
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
my $any_keyword_changes;
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{keywords})
|
|
|
|
{
|
|
|
|
foreach my $b (@bug_objects)
|
|
|
|
{
|
|
|
|
my $return = $b->modify_keywords(
|
|
|
|
$ARGS->{keywords},
|
|
|
|
$ARGS->{keywords_description},
|
|
|
|
$ARGS->{keywordaction},
|
|
|
|
);
|
2008-12-15 15:53:33 +03:00
|
|
|
$any_keyword_changes ||= $return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Component, target_milestone, and version are in here just in case
|
|
|
|
# the 'product' field wasn't defined in the CGI. It doesn't hurt to set
|
|
|
|
# them twice.
|
|
|
|
my @custom_fields = Bugzilla->active_custom_fields;
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
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
|
|
|
|
priority status_whiteboard short_desc target_milestone bug_file_loc version
|
2008-12-15 15:53:33 +03:00
|
|
|
);
|
2008-12-22 18:43:16 +03:00
|
|
|
|
|
|
|
foreach my $b (@bug_objects)
|
|
|
|
{
|
2011-10-04 18:01:24 +04:00
|
|
|
if ($ARGS->{comment} !~ /^\s*$/ || $ARGS->{work_time})
|
2008-12-22 18:43:16 +03:00
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# Add a comment as needed to each bug. This is done early because
|
|
|
|
# there are lots of things that want to check if we added a comment.
|
2011-10-04 18:01:24 +04:00
|
|
|
$b->add_comment($ARGS->{comment}, {
|
|
|
|
isprivate => $ARGS->{commentprivacy},
|
|
|
|
work_time => $ARGS->{work_time},
|
|
|
|
type => $ARGS->{cmt_worktime} ? CMT_WORKTIME : CMT_NORMAL,
|
|
|
|
});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2008-12-22 18:43:16 +03:00
|
|
|
foreach my $field_name (@set_fields)
|
|
|
|
{
|
2011-10-04 18:01:24 +04:00
|
|
|
if (defined $ARGS->{$field_name} ||
|
|
|
|
defined $ARGS->{product} && $field_name =~ /^(component|target_milestone|version)$/)
|
2008-12-22 18:43:16 +03:00
|
|
|
{
|
2014-03-08 02:36:38 +04:00
|
|
|
if (my $m = $methods->{$field_name})
|
|
|
|
{
|
|
|
|
$b->$m($ARGS->{$field_name} || '');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$b->set($field_name, $ARGS->{$field_name} || '');
|
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
$b->reset_assigned_to if $ARGS->{set_default_assignee};
|
|
|
|
$b->reset_qa_contact if $ARGS->{set_default_qa_contact};
|
2008-12-15 15:53:33 +03:00
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
if (defined $ARGS->{see_also})
|
|
|
|
{
|
|
|
|
my @see_also = split ',', $ARGS->{see_also};
|
2009-07-29 15:21:49 +04:00
|
|
|
$b->add_see_also($_) foreach @see_also;
|
|
|
|
}
|
2014-03-31 17:22:50 +04:00
|
|
|
if (defined $ARGS->{remove_see_also}) # FIXME array[]
|
2014-03-08 02:36:38 +04:00
|
|
|
{
|
2014-03-31 17:22:50 +04:00
|
|
|
$b->remove_see_also($_) foreach ref $ARGS->{remove_see_also} ? @{$ARGS->{remove_see_also}} : $ARGS->{remove_see_also};
|
2009-07-29 15:21:49 +04:00
|
|
|
}
|
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# And set custom fields.
|
2008-12-22 18:43:16 +03:00
|
|
|
foreach my $field (@custom_fields)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
my $fname = $field->name;
|
2014-03-31 17:22:50 +04:00
|
|
|
if (defined $ARGS->{$fname} || defined $ARGS->{"defined_$fname"}) # FIXME array[] for multiselects
|
2008-12-22 18:43:16 +03:00
|
|
|
{
|
2014-03-08 02:36:38 +04:00
|
|
|
$b->set_custom_field($field, $ARGS->{$fname});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
2013-10-01 19:19:45 +04:00
|
|
|
|
|
|
|
# CustIS Bug 134368 - Edit comment
|
2013-09-26 12:04:33 +04:00
|
|
|
if (%edit_comment)
|
|
|
|
{
|
2013-10-01 19:19:45 +04:00
|
|
|
foreach my $comment_id (keys %edit_comment)
|
|
|
|
{
|
|
|
|
$b->edit_comment($comment_id, $edit_comment{$comment_id});
|
2013-09-26 12:04:33 +04:00
|
|
|
}
|
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
# Certain changes can only happen on individual bugs, never on mass-changes.
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{id})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# Since aliases are unique (like bug numbers), they can only be changed
|
|
|
|
# for one bug at a time.
|
2014-03-08 02:36:38 +04:00
|
|
|
if (Bugzilla->params->{usebugaliases} && defined $ARGS->{alias})
|
|
|
|
{
|
|
|
|
$first_bug->set('alias', $ARGS->{alias});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
# reporter_accessible and cclist_accessible--these are only set if
|
|
|
|
# the user can change them and they appear on the page.
|
2014-03-08 02:36:38 +04:00
|
|
|
if (defined $ARGS->{cclist_accessible} || defined $ARGS->{defined_cclist_accessible})
|
|
|
|
{
|
2014-03-31 17:22:50 +04:00
|
|
|
$first_bug->set('cclist_accessible', $ARGS->{cclist_accessible});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
if (defined $ARGS->{reporter_accessible} || defined $ARGS->{defined_reporter_accessible})
|
|
|
|
{
|
2014-03-31 17:22:50 +04:00
|
|
|
$first_bug->set('reporter_accessible', $ARGS->{reporter_accessible});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2010-09-27 20:20:16 +04:00
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# You can only mark/unmark comments as private on single bugs. If
|
|
|
|
# you're not in the insider group, this code won't do anything.
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $key (keys %$ARGS)
|
|
|
|
{
|
|
|
|
if (/^defined_isprivate_(\d+)$/)
|
|
|
|
{
|
|
|
|
my $comment_id = $1;
|
|
|
|
$first_bug->set_comment_is_private($comment_id, $ARGS->{"isprivate_$comment_id"});
|
|
|
|
}
|
2011-10-04 18:01:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
# Same with worktime-only
|
|
|
|
foreach (keys %$ARGS)
|
|
|
|
{
|
2011-10-21 18:47:46 +04:00
|
|
|
if (/^cmt_(normal|worktime)_(\d+)$/ && $ARGS->{$_})
|
2011-10-04 18:01:24 +04:00
|
|
|
{
|
|
|
|
$first_bug->set_comment_worktimeonly($2, $1 eq 'worktime');
|
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
# We need to check the addresses involved in a CC change before we touch
|
2008-12-15 15:53:33 +03:00
|
|
|
# any bugs. What we'll do here is formulate the CC data into two arrays of
|
2014-03-08 02:36:38 +04:00
|
|
|
# users involved in this CC change. Then those arrays can be used later
|
2008-12-15 15:53:33 +03:00
|
|
|
# on for the actual change.
|
|
|
|
my (@cc_add, @cc_remove);
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{newcc} || $ARGS->{addselfcc} || $ARGS->{removecc} || $ARGS->{masscc})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# If masscc is defined, then we came from buglist and need to either add or
|
|
|
|
# remove cc's... otherwise, we came from bugform and may need to do both.
|
|
|
|
my ($cc_add, $cc_remove) = "";
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($ARGS->{masscc})
|
|
|
|
{
|
|
|
|
if ($ARGS->{ccaction} eq 'add')
|
|
|
|
{
|
|
|
|
$cc_add = $ARGS->{masscc};
|
|
|
|
}
|
|
|
|
elsif ($ARGS->{ccaction} eq 'remove')
|
|
|
|
{
|
|
|
|
$cc_remove = $ARGS->{masscc};
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
$cc_add = $ARGS->{newcc};
|
2008-12-15 15:53:33 +03:00
|
|
|
# We came from bug_form which uses a select box to determine what cc's
|
|
|
|
# need to be removed...
|
2014-03-31 17:22:50 +04:00
|
|
|
if (defined $ARGS->{removecc} && $ARGS->{cc}) # FIXME array[]
|
2014-03-08 02:36:38 +04:00
|
|
|
{
|
|
|
|
$cc_remove = join ",", @{$ARGS->{cc}};
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
push @cc_add, split /[\s,]+/, $cc_add if $cc_add;
|
|
|
|
push @cc_add, Bugzilla->user if defined $ARGS->{addselfcc};
|
|
|
|
push @cc_remove, split /[\s,]+/, $cc_remove if $cc_remove;
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $b (@bug_objects)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
$b->remove_cc($_) foreach @cc_remove;
|
|
|
|
$b->add_cc($_) foreach @cc_add;
|
|
|
|
# Theoretically you could move a product without ever specifying
|
|
|
|
# a new assignee or qa_contact, or adding/removing any CCs. So,
|
|
|
|
# we have to check that the current assignee, qa, and CCs are still
|
|
|
|
# valid if we've switched products, under strict_isolation. We can only
|
|
|
|
# do that here. There ought to be some better way to do this,
|
|
|
|
# architecturally, but I haven't come up with it.
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($product_change)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
$b->_check_strict_isolation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:55:21 +04:00
|
|
|
# TODO move saved state into a global object
|
2010-06-04 23:09:20 +04:00
|
|
|
my $send_results = [];
|
2011-03-29 12:55:21 +04:00
|
|
|
my $send_attrs = {};
|
2010-06-04 23:09:20 +04:00
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
my $move_action = $ARGS->{action} || '';
|
|
|
|
if ($move_action eq Bugzilla->params->{'move-button-text'})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
Bugzilla->params->{'move-enabled'} || ThrowUserError("move_bugs_disabled");
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
$user->is_mover || ThrowUserError("auth_failure", { action => 'move', object => 'bugs' });
|
2008-12-15 15:53:33 +03:00
|
|
|
|
|
|
|
$dbh->bz_start_transaction();
|
|
|
|
|
|
|
|
# First update all moved bugs.
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $bug (@bug_objects)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
$bug->add_comment('', { type => CMT_MOVED_TO, extra_data => $user->login });
|
|
|
|
}
|
|
|
|
# Don't export the new status and resolution. We want the current ones.
|
|
|
|
local $Storable::forgive_me = 1;
|
|
|
|
my $bugs = dclone(\@bug_objects);
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
my $new_status = Bugzilla->params->{duplicate_or_move_bug_status};
|
|
|
|
foreach my $bug (@bug_objects)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
$bug->set_status($new_status, {resolution => 'MOVED', moving => 1});
|
|
|
|
}
|
|
|
|
$_->update() foreach @bug_objects;
|
|
|
|
$dbh->bz_commit_transaction();
|
|
|
|
|
|
|
|
# Now send emails.
|
|
|
|
foreach my $bug (@bug_objects) {
|
2010-09-27 20:20:16 +04:00
|
|
|
push @$send_results, send_results({
|
2010-06-04 23:09:20 +04:00
|
|
|
mailrecipients => { 'changer' => $user->login },
|
2010-09-27 20:20:16 +04:00
|
|
|
bug_id => $bug->id,
|
2010-06-04 23:09:20 +04:00
|
|
|
type => 'move',
|
|
|
|
});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
# Prepare and send all data about these bugs to the new database
|
|
|
|
my $to = Bugzilla->params->{'move-to-address'};
|
|
|
|
$to =~ s/@/\@/;
|
|
|
|
my $from = Bugzilla->params->{'moved-from-address'};
|
|
|
|
$from =~ s/@/\@/;
|
|
|
|
my $msg = "To: $to\n";
|
|
|
|
$msg .= "From: Bugzilla <" . $from . ">\n";
|
|
|
|
$msg .= "Subject: Moving bug(s) " . join(', ', map($_->id, @bug_objects))
|
|
|
|
. "\n\n";
|
|
|
|
|
|
|
|
my @fieldlist = (Bugzilla::Bug->fields, 'group', 'long_desc',
|
|
|
|
'attachment', 'attachmentdata');
|
|
|
|
my %displayfields;
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach (@fieldlist)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
$displayfields{$_} = 1;
|
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
$template->process("bug/show.xml.tmpl", {
|
|
|
|
bugs => $bugs,
|
|
|
|
displayfields => \%displayfields,
|
|
|
|
}, \$msg) || ThrowTemplateError($template->error());
|
2008-12-15 15:53:33 +03:00
|
|
|
|
|
|
|
$msg .= "\n";
|
|
|
|
MessageToMTA($msg);
|
|
|
|
|
|
|
|
# End the response page.
|
2014-03-08 02:36:38 +04:00
|
|
|
unless (Bugzilla->usage_mode == USAGE_MODE_EMAIL)
|
|
|
|
{
|
2010-06-04 23:09:20 +04:00
|
|
|
foreach (@$send_results)
|
|
|
|
{
|
|
|
|
$template->process("bug/process/results.html.tmpl", { %$vars, %$_ })
|
|
|
|
|| ThrowTemplateError($template->error());
|
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
$template->process("bug/navigate.html.tmpl", $vars)
|
|
|
|
|| ThrowTemplateError($template->error());
|
|
|
|
$template->process("global/footer.html.tmpl", $vars)
|
|
|
|
|| ThrowTemplateError($template->error());
|
|
|
|
}
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# You cannot mark bugs as duplicates when changing several bugs at once
|
|
|
|
# (because currently there is no way to check for duplicate loops in that
|
|
|
|
# situation).
|
2014-03-08 02:36:38 +04:00
|
|
|
if (!$ARGS->{id} && $ARGS->{dup_id})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
ThrowUserError('dupe_not_allowed');
|
|
|
|
}
|
|
|
|
|
|
|
|
# Set the status, resolution, and dupe_of (if needed). This has to be done
|
|
|
|
# down here, because the validity of status changes depends on other fields,
|
|
|
|
# such as Target Milestone.
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $b (@bug_objects)
|
|
|
|
{
|
|
|
|
if (defined $ARGS->{bug_status})
|
|
|
|
{
|
|
|
|
$b->set_status($ARGS->{bug_status}, {
|
|
|
|
resolution => $ARGS->{resolution},
|
|
|
|
dupe_of => $ARGS->{dup_id},
|
|
|
|
});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
elsif (defined $ARGS->{resolution})
|
|
|
|
{
|
|
|
|
$b->set_resolution($ARGS->{resolution}, { dupe_of => $ARGS->{dup_id} });
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2014-03-08 02:36:38 +04:00
|
|
|
elsif (defined $ARGS->{dup_id})
|
|
|
|
{
|
|
|
|
$b->set_dup_id($ARGS->{dup_id});
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-30 23:15:54 +04:00
|
|
|
Bugzilla::Hook::process('process_bug-pre_update', { bugs => \@bug_objects });
|
|
|
|
|
|
|
|
# @msgs will store emails which have to be sent to voters, if any.
|
|
|
|
my @msgs;
|
|
|
|
|
2011-08-26 18:40:49 +04:00
|
|
|
Bugzilla->request_cache->{checkers_hide_error} = 1 if @bug_objects > 1;
|
2010-10-22 20:57:14 +04:00
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
##############################
|
|
|
|
# Do Actual Database Updates #
|
|
|
|
##############################
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $bug (@bug_objects)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
$dbh->bz_start_transaction();
|
|
|
|
|
2013-07-12 17:23:01 +04:00
|
|
|
my $mail_count = @{Bugzilla->get_mail_result()};
|
2010-05-15 00:02:34 +04:00
|
|
|
my $timestamp = $dbh->selectrow_array(q{SELECT LOCALTIMESTAMP(0)});
|
2013-07-12 15:32:27 +04:00
|
|
|
my $changes = $bug->update($timestamp);
|
2008-12-15 15:53:33 +03:00
|
|
|
|
2011-08-26 18:40:49 +04:00
|
|
|
if ($bug->{failed_checkers} && @{$bug->{failed_checkers}} &&
|
|
|
|
!$bug->{passed_checkers})
|
2010-10-22 20:57:14 +04:00
|
|
|
{
|
2011-08-26 18:40:49 +04:00
|
|
|
# This means update is blocked
|
|
|
|
# and rollback_to_savepoint is already done in Checkers.pm
|
2013-07-12 17:23:01 +04:00
|
|
|
# Roll back flag mail
|
|
|
|
splice @{Bugzilla->get_mail_result()}, $mail_count;
|
2011-08-26 18:40:49 +04:00
|
|
|
next;
|
2010-10-22 20:57:14 +04:00
|
|
|
}
|
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
my %notify_deps;
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($changes->{bug_status})
|
|
|
|
{
|
|
|
|
my ($old_status, $new_status) = @{ $changes->{bug_status} };
|
2010-09-27 20:20:16 +04:00
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# If this bug has changed from opened to closed or vice-versa,
|
|
|
|
# then all of the bugs we block need to be notified.
|
2014-03-08 02:36:38 +04:00
|
|
|
if (is_open_state($old_status) ne is_open_state($new_status))
|
|
|
|
{
|
|
|
|
$notify_deps{$_} = 1 foreach @{$bug->blocked};
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
2010-09-27 20:20:16 +04:00
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# We may have zeroed the remaining time, if we moved into a closed
|
|
|
|
# status, so we should inform the user about that.
|
2009-11-25 19:53:10 +03:00
|
|
|
if (!is_open_state($new_status) && $changes->{remaining_time} &&
|
|
|
|
!$changes->{remaining_time}->[1] &&
|
2009-11-25 19:52:16 +03:00
|
|
|
Bugzilla->user->in_group(Bugzilla->params->{timetrackinggroup}))
|
|
|
|
{
|
|
|
|
$vars->{message} = "remaining_time_zeroed";
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-15 00:02:34 +04:00
|
|
|
# CustIS Bug 38616 - CC list restriction
|
2009-12-02 16:39:36 +03:00
|
|
|
if ($bug->{restricted_cc})
|
|
|
|
{
|
2013-12-12 17:55:18 +04:00
|
|
|
$vars->{restricted_cc} = [map { $_->login } @{$bug->{restricted_cc}}];
|
2014-03-31 18:04:19 +04:00
|
|
|
$vars->{cc_restrict_group} = $bug->product_obj->cc_group;
|
2009-12-02 16:39:36 +03:00
|
|
|
$vars->{message} = 'cc_list_restricted';
|
|
|
|
}
|
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# To get a list of all changed dependencies, convert the "changes" arrays
|
|
|
|
# into a long string, then collapse that string into unique numbers in
|
|
|
|
# a hash.
|
2014-03-08 02:36:38 +04:00
|
|
|
my $all_changed_deps = join(', ', @{ $changes->{dependson} || [] });
|
|
|
|
$all_changed_deps = join(', ', @{ $changes->{blocked} || [] }, $all_changed_deps);
|
2008-12-15 15:53:33 +03:00
|
|
|
my %changed_deps = map { $_ => 1 } split(', ', $all_changed_deps);
|
|
|
|
# When clearning one field (say, blocks) and filling in the other
|
|
|
|
# (say, dependson), an empty string can get into the hash and cause
|
|
|
|
# an error later.
|
|
|
|
delete $changed_deps{''};
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($changes->{product})
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# If some votes have been removed, RemoveVotes() returns
|
|
|
|
# a list of messages to send to voters.
|
2009-07-29 15:21:49 +04:00
|
|
|
# We delay the sending of these messages till changes are committed.
|
2010-06-30 23:15:54 +04:00
|
|
|
push @msgs, RemoveVotes($bug->id, 0, 'votes_bug_moved');
|
2009-07-13 17:54:45 +04:00
|
|
|
CheckIfVotedConfirmed($bug->id);
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
$dbh->bz_commit_transaction();
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
my $old_qa = $changes->{qa_contact} ? $changes->{qa_contact}->[0] : '';
|
|
|
|
my $old_own = $changes->{assigned_to} ? $changes->{assigned_to}->[0] : '';
|
|
|
|
my $old_cc = $changes->{cc} ? $changes->{cc}->[0] : '';
|
2010-06-04 23:09:20 +04:00
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# Let the user know the bug was changed and who did and didn't
|
|
|
|
# receive email about the change.
|
2010-06-30 23:15:54 +04:00
|
|
|
push @$send_results, {
|
2010-06-04 23:09:20 +04:00
|
|
|
mailrecipients => {
|
|
|
|
cc => [split(/[\s,]+/, $old_cc)],
|
|
|
|
owner => $old_own,
|
|
|
|
qacontact => $old_qa,
|
|
|
|
changer => Bugzilla->user->login,
|
|
|
|
},
|
2010-09-27 20:20:16 +04:00
|
|
|
bug_id => $bug->id,
|
2010-06-04 23:09:20 +04:00
|
|
|
type => "bug",
|
2010-06-30 23:15:54 +04:00
|
|
|
};
|
|
|
|
|
2008-12-15 15:53:33 +03:00
|
|
|
# If the bug was marked as a duplicate, we need to notify users on the
|
|
|
|
# other bug of any changes to that bug.
|
2014-03-08 02:36:38 +04:00
|
|
|
my $new_dup_id = $changes->{dup_id} ? $changes->{dup_id}->[1] : undef;
|
|
|
|
if ($new_dup_id)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# Let the user know a duplication notation was added to the
|
|
|
|
# original bug.
|
2010-06-30 23:15:54 +04:00
|
|
|
push @$send_results, {
|
2010-06-04 23:09:20 +04:00
|
|
|
mailrecipients => { changer => Bugzilla->user->login },
|
2010-09-27 20:20:16 +04:00
|
|
|
bug_id => $new_dup_id,
|
2010-06-04 23:09:20 +04:00
|
|
|
type => "dupe",
|
2010-06-30 23:15:54 +04:00
|
|
|
};
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
my %all_dep_changes = (%notify_deps, %changed_deps);
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $id (sort { $a <=> $b } (keys %all_dep_changes))
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# Let the user (if he is able to see the bug) know we checked to
|
|
|
|
# see if we should email notice of this change to users with a
|
|
|
|
# relationship to the dependent bug and who did and didn't
|
|
|
|
# receive email about it.
|
2010-06-30 23:15:54 +04:00
|
|
|
push @$send_results, {
|
2010-06-04 23:09:20 +04:00
|
|
|
mailrecipients => { changer => Bugzilla->user->login },
|
2010-09-27 20:20:16 +04:00
|
|
|
bug_id => $id,
|
2010-06-04 23:09:20 +04:00
|
|
|
type => "dep",
|
2010-06-30 23:15:54 +04:00
|
|
|
};
|
2008-12-15 15:53:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-29 12:55:21 +04:00
|
|
|
# CustIS Bug 68919 - Create multiple attachments to bug
|
|
|
|
if (@bug_objects == 1)
|
|
|
|
{
|
|
|
|
Bugzilla::Attachment::add_multiple($first_bug, $cgi, $send_attrs);
|
|
|
|
}
|
|
|
|
|
2010-06-30 23:15:54 +04:00
|
|
|
$dbh->bz_commit_transaction();
|
|
|
|
|
|
|
|
###############
|
|
|
|
# Send Emails #
|
|
|
|
###############
|
|
|
|
|
2010-09-27 20:20:16 +04:00
|
|
|
# TODO move votes removed mail to BugMail
|
2010-06-30 23:15:54 +04:00
|
|
|
# Now is a good time to send email to voters.
|
2014-03-08 02:36:38 +04:00
|
|
|
foreach my $msg (@msgs)
|
|
|
|
{
|
2010-06-30 23:15:54 +04:00
|
|
|
MessageToMTA($msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Send bugmail
|
2013-07-12 11:23:30 +04:00
|
|
|
|
2013-08-22 16:33:55 +04:00
|
|
|
# Add flag notifications to send_results
|
2013-07-12 15:59:55 +04:00
|
|
|
my $notify = Bugzilla->get_mail_result();
|
2013-07-12 16:07:21 +04:00
|
|
|
push @$send_results, @$notify;
|
2013-07-12 11:23:30 +04:00
|
|
|
|
2010-09-27 20:20:16 +04:00
|
|
|
send_results($_) for @$send_results;
|
|
|
|
$vars->{sentmail} = $send_results;
|
2011-08-26 18:40:49 +04:00
|
|
|
$vars->{failed_checkers} = Bugzilla->request_cache->{failed_checkers};
|
2010-06-30 23:15:54 +04:00
|
|
|
|
2010-06-04 23:09:20 +04:00
|
|
|
my $bug;
|
2014-03-08 02:36:38 +04:00
|
|
|
if (Bugzilla->usage_mode == USAGE_MODE_EMAIL)
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
# Do nothing.
|
|
|
|
}
|
2010-09-27 20:20:16 +04:00
|
|
|
elsif (($action eq 'next_bug' or $action eq 'same_bug') && ($bug = $vars->{bug}) && $user->can_see_bug($bug))
|
|
|
|
{
|
|
|
|
if ($action eq 'same_bug')
|
|
|
|
{
|
2010-06-04 23:09:20 +04:00
|
|
|
# $bug->update() does not update the internal structure of
|
|
|
|
# the bug sufficiently to display the bug with the new values.
|
|
|
|
# (That is, if we just passed in the old Bug object, we'd get
|
|
|
|
# a lot of old values displayed.)
|
|
|
|
$bug = new Bugzilla::Bug($bug->id);
|
2014-03-08 02:36:38 +04:00
|
|
|
$vars->{bug} = $bug;
|
2010-06-04 23:09:20 +04:00
|
|
|
}
|
|
|
|
# Do redirect and exit
|
2010-06-07 20:24:18 +04:00
|
|
|
my $title;
|
|
|
|
if (scalar(@bug_objects) == 1)
|
|
|
|
{
|
2012-05-02 16:38:10 +04:00
|
|
|
# FIXME hard-coded template title, also in bug/show-header.html.tmpl
|
|
|
|
$title = Bugzilla->messages->{terms}->{Bug} . ' ' . $bug_objects[0]->id . ' processed – ' .
|
|
|
|
$bug->short_desc . ' – ' . $bug->product . '/' . $bug->component . ' – ' .
|
|
|
|
$bug->bug_status . ' ' . $bug->resolution;
|
2010-06-07 20:24:18 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-07-20 16:48:26 +04:00
|
|
|
$title = Bugzilla->messages->{terms}->{Bugs} . ' processed';
|
2010-06-07 20:24:18 +04:00
|
|
|
}
|
2011-03-29 12:55:21 +04:00
|
|
|
$send_attrs->{nextbug} = $action eq 'next_bug' ? 1 : 0;
|
2010-10-05 21:40:17 +04:00
|
|
|
my $ses = {
|
|
|
|
sent => $send_results,
|
|
|
|
title => $title,
|
2011-03-29 12:55:21 +04:00
|
|
|
sent_attrs => $send_attrs,
|
2010-10-22 20:57:14 +04:00
|
|
|
# CustIS Bug 68921 - Correctness checkers
|
2011-08-26 18:40:49 +04:00
|
|
|
failed_checkers => Checkers::freeze_failed_checkers(Bugzilla->request_cache->{failed_checkers}),
|
2010-10-05 21:40:17 +04:00
|
|
|
};
|
|
|
|
# CustIS Bug 38616 - CC list restriction
|
|
|
|
if (scalar(@bug_objects) == 1 && $bug_objects[0]->{restricted_cc})
|
|
|
|
{
|
|
|
|
$ses->{message_vars} = {
|
|
|
|
restricted_cc => [ map { $_->login } @{ $bug_objects[0]->{restricted_cc} } ],
|
2014-03-31 18:04:19 +04:00
|
|
|
cc_restrict_group => $bug_objects[0]->product_obj->cc_group,
|
2010-10-05 21:40:17 +04:00
|
|
|
};
|
|
|
|
$ses->{message} = 'cc_list_restricted';
|
|
|
|
}
|
|
|
|
if (Bugzilla->save_session_data($ses))
|
2010-06-04 23:09:20 +04:00
|
|
|
{
|
|
|
|
print $cgi->redirect(-location => 'show_bug.cgi?id='.$bug->id);
|
2008-12-15 15:53:33 +03:00
|
|
|
exit;
|
|
|
|
}
|
2010-06-04 23:09:20 +04:00
|
|
|
}
|
|
|
|
|
2014-03-08 02:36:38 +04:00
|
|
|
if ($action ne 'nothing' && $action ne 'next_bug' && $action ne 'same_bug')
|
|
|
|
{
|
2008-12-15 15:53:33 +03:00
|
|
|
ThrowCodeError("invalid_post_bug_submit_action");
|
|
|
|
}
|
|
|
|
|
|
|
|
# End the response page.
|
2010-06-04 23:09:20 +04:00
|
|
|
unless (Bugzilla->usage_mode == USAGE_MODE_EMAIL)
|
|
|
|
{
|
|
|
|
foreach (@$send_results)
|
|
|
|
{
|
|
|
|
$template->process("bug/process/results.html.tmpl", { %$vars, %$_ })
|
|
|
|
|| ThrowTemplateError($template->error());
|
2010-06-07 20:24:18 +04:00
|
|
|
$vars->{header_done} = 1;
|
2010-06-04 23:09:20 +04:00
|
|
|
}
|
2010-10-22 20:57:14 +04:00
|
|
|
if (!$vars->{header_done})
|
|
|
|
{
|
|
|
|
$template->process("global/header.html.tmpl", $vars)
|
|
|
|
|| ThrowTemplateError($template->error());
|
|
|
|
}
|
2008-12-15 15:53:33 +03:00
|
|
|
$template->process("bug/navigate.html.tmpl", $vars)
|
|
|
|
|| ThrowTemplateError($template->error());
|
|
|
|
$template->process("global/footer.html.tmpl", $vars)
|
|
|
|
|| ThrowTemplateError($template->error());
|
|
|
|
}
|
|
|
|
|
2010-09-27 20:20:16 +04:00
|
|
|
$vars;
|
|
|
|
__END__
|