Commit d4bcf527 authored by lpsolit%gmail.com's avatar lpsolit%gmail.com

Bug 353656: User Interface gets corrupted by multiple localized users resolving…

Bug 353656: User Interface gets corrupted by multiple localized users resolving bugs as duplicates - Patch by Fré©ric Buclin <LpSolit@gmail.com> r=bkor a=justdave
parent b692a5a6
...@@ -1315,12 +1315,16 @@ sub bug_alias_to_id { ...@@ -1315,12 +1315,16 @@ sub bug_alias_to_id {
##################################################################### #####################################################################
sub AppendComment { sub AppendComment {
my ($bugid, $whoid, $comment, $isprivate, $timestamp, $work_time) = @_; my ($bugid, $whoid, $comment, $isprivate, $timestamp, $work_time,
$type, $extra_data) = @_;
$work_time ||= 0; $work_time ||= 0;
$type ||= CMT_NORMAL;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
ValidateTime($work_time, "work_time") if $work_time; ValidateTime($work_time, "work_time") if $work_time;
trick_taint($work_time); trick_taint($work_time);
detaint_natural($type)
|| ThrowCodeError('bad_arg', {argument => 'type', function => 'AppendComment'});
# Use the date/time we were given if possible (allowing calling code # Use the date/time we were given if possible (allowing calling code
# to synchronize the comment's timestamp with those of other records). # to synchronize the comment's timestamp with those of other records).
...@@ -1329,7 +1333,7 @@ sub AppendComment { ...@@ -1329,7 +1333,7 @@ sub AppendComment {
$comment =~ s/\r\n/\n/g; # Handle Windows-style line endings. $comment =~ s/\r\n/\n/g; # Handle Windows-style line endings.
$comment =~ s/\r/\n/g; # Handle Mac-style line endings. $comment =~ s/\r/\n/g; # Handle Mac-style line endings.
if ($comment =~ /^\s*$/) { # Nothin' but whitespace if ($comment =~ /^\s*$/ && !$type) { # Nothin' but whitespace
return; return;
} }
...@@ -1338,9 +1342,11 @@ sub AppendComment { ...@@ -1338,9 +1342,11 @@ sub AppendComment {
trick_taint($comment); trick_taint($comment);
my $privacyval = $isprivate ? 1 : 0 ; my $privacyval = $isprivate ? 1 : 0 ;
$dbh->do(q{INSERT INTO longdescs $dbh->do(q{INSERT INTO longdescs
(bug_id, who, bug_when, thetext, isprivate, work_time) (bug_id, who, bug_when, thetext, isprivate, work_time,
VALUES (?,?,?,?,?,?)}, undef, type, extra_data)
($bugid, $whoid, $timestamp, $comment, $privacyval, $work_time)); VALUES (?, ?, ?, ?, ?, ?, ?, ?)}, undef,
($bugid, $whoid, $timestamp, $comment, $privacyval, $work_time,
$type, $extra_data));
$dbh->do("UPDATE bugs SET delta_ts = ? WHERE bug_id = ?", $dbh->do("UPDATE bugs SET delta_ts = ? WHERE bug_id = ?",
undef, $timestamp, $bugid); undef, $timestamp, $bugid);
} }
...@@ -1402,29 +1408,54 @@ sub ValidateTime { ...@@ -1402,29 +1408,54 @@ sub ValidateTime {
} }
sub GetComments { sub GetComments {
my ($id, $comment_sort_order) = (@_); my ($id, $comment_sort_order, $start, $end) = @_;
my $dbh = Bugzilla->dbh;
$comment_sort_order = $comment_sort_order || $comment_sort_order = $comment_sort_order ||
Bugzilla->user->settings->{'comment_sort_order'}->{'value'}; Bugzilla->user->settings->{'comment_sort_order'}->{'value'};
my $sort_order = ($comment_sort_order eq "oldest_to_newest") ? 'asc' : 'desc'; my $sort_order = ($comment_sort_order eq "oldest_to_newest") ? 'asc' : 'desc';
my $dbh = Bugzilla->dbh;
my @comments; my @comments;
my $sth = $dbh->prepare( my @args = ($id);
"SELECT profiles.realname AS name, profiles.login_name AS email,
" . $dbh->sql_date_format('longdescs.bug_when', '%Y.%m.%d %H:%i:%s') . " my $query = 'SELECT profiles.realname AS name, profiles.login_name AS email, ' .
AS time, longdescs.thetext AS body, longdescs.work_time, $dbh->sql_date_format('longdescs.bug_when', '%Y.%m.%d %H:%i:%s') .
isprivate, already_wrapped ' AS time, longdescs.thetext AS body, longdescs.work_time,
FROM longdescs, profiles isprivate, already_wrapped, type, extra_data
WHERE profiles.userid = longdescs.who FROM longdescs
AND longdescs.bug_id = ? INNER JOIN profiles
ORDER BY longdescs.bug_when $sort_order"); ON profiles.userid = longdescs.who
$sth->execute($id); WHERE longdescs.bug_id = ?';
if ($start) {
$query .= ' AND longdescs.bug_when > ?
AND longdescs.bug_when <= ?';
push(@args, ($start, $end));
}
$query .= " ORDER BY longdescs.bug_when $sort_order";
my $sth = $dbh->prepare($query);
$sth->execute(@args);
while (my $comment_ref = $sth->fetchrow_hashref()) { while (my $comment_ref = $sth->fetchrow_hashref()) {
my %comment = %$comment_ref; my %comment = %$comment_ref;
$comment{'email'} .= Bugzilla->params->{'emailsuffix'}; $comment{'email'} .= Bugzilla->params->{'emailsuffix'};
$comment{'name'} = $comment{'name'} || $comment{'email'}; $comment{'name'} = $comment{'name'} || $comment{'email'};
if ($comment{'type'} == CMT_DUPE_OF) {
$comment{'body'} .= "\n\n" . get_text('bug_duplicate_of',
{ dupe_of => $comment{'extra_data'} });
}
elsif ($comment{'type'} == CMT_HAS_DUPE) {
$comment{'body'} = get_text('bug_has_duplicate',
{ dupe => $comment{'extra_data'} });
}
elsif ($comment{'type'} == CMT_POPULAR_VOTES) {
$comment{'body'} = get_text('bug_confirmed_by_votes');
}
elsif ($comment{'type'} == CMT_MOVED_TO) {
$comment{'body'} .= "\n\n" . get_text('bug_moved_to',
{ login => $comment{'extra_data'} });
}
push (@comments, \%comment); push (@comments, \%comment);
} }
...@@ -1760,9 +1791,7 @@ sub CheckIfVotedConfirmed { ...@@ -1760,9 +1791,7 @@ sub CheckIfVotedConfirmed {
"VALUES (?, ?, ?, ?, ?, ?)", "VALUES (?, ?, ?, ?, ?, ?)",
undef, ($id, $who, $timestamp, $fieldid, '0', '1')); undef, ($id, $who, $timestamp, $fieldid, '0', '1'));
AppendComment($id, $who, AppendComment($id, $who, "", 0, $timestamp, 0, CMT_POPULAR_VOTES);
"*** This bug has been confirmed by popular vote. ***",
0, $timestamp);
$ret = 1; $ret = 1;
} }
......
...@@ -652,17 +652,6 @@ sub get_comments_by_bug { ...@@ -652,17 +652,6 @@ sub get_comments_by_bug {
my $count = 0; my $count = 0;
my $anyprivate = 0; my $anyprivate = 0;
my $query = 'SELECT profiles.login_name, profiles.realname, ' .
$dbh->sql_date_format('longdescs.bug_when', '%Y.%m.%d %H:%i') . ',
longdescs.thetext, longdescs.isprivate,
longdescs.already_wrapped
FROM longdescs
INNER JOIN profiles
ON profiles.userid = longdescs.who
WHERE longdescs.bug_id = ? ';
my @args = ($id);
# $start will be undef for new bugs, and defined for pre-existing bugs. # $start will be undef for new bugs, and defined for pre-existing bugs.
if ($start) { if ($start) {
# If $start is not NULL, obtain the count-index # If $start is not NULL, obtain the count-index
...@@ -670,26 +659,21 @@ sub get_comments_by_bug { ...@@ -670,26 +659,21 @@ sub get_comments_by_bug {
$count = $dbh->selectrow_array('SELECT COUNT(*) FROM longdescs $count = $dbh->selectrow_array('SELECT COUNT(*) FROM longdescs
WHERE bug_id = ? AND bug_when <= ?', WHERE bug_id = ? AND bug_when <= ?',
undef, ($id, $start)); undef, ($id, $start));
$query .= ' AND longdescs.bug_when > ?
AND longdescs.bug_when <= ? ';
push @args, ($start, $end);
} }
$query .= ' ORDER BY longdescs.bug_when'; my $comments = Bugzilla::Bug::GetComments($id, "oldest_to_newest", $start, $end);
my $comments = $dbh->selectall_arrayref($query, undef, @args);
foreach (@$comments) { foreach my $comment (@$comments) {
my ($who, $whoname, $when, $text, $isprivate, $already_wrapped) = @$_;
if ($count) { if ($count) {
$result .= "\n\n--- Comment #$count from $whoname <$who" . $result .= "\n\n--- Comment #$count from " . $comment->{'name'} . " <" .
Bugzilla->params->{'emailsuffix'}. "> " $comment->{'email'} . Bugzilla->params->{'emailsuffix'} . "> " .
. format_time($when) . " ---\n"; format_time($comment->{'time'}) . " ---\n";
} }
if ($isprivate > 0 && Bugzilla->params->{'insidergroup'}) { if ($comment->{'isprivate'} > 0 && Bugzilla->params->{'insidergroup'}) {
$anyprivate = 1; $anyprivate = 1;
} }
$result .= ($already_wrapped ? $text : wrap_comment($text)); $result .= ($comment->{'already_wrapped'} ? $comment->{'body'}
: wrap_comment($comment->{'body'}));
$count++; $count++;
} }
return ($result, $anyprivate); return ($result, $anyprivate);
......
...@@ -81,6 +81,12 @@ use File::Basename; ...@@ -81,6 +81,12 @@ use File::Basename;
COMMENT_COLS COMMENT_COLS
CMT_NORMAL
CMT_DUPE_OF
CMT_HAS_DUPE
CMT_POPULAR_VOTES
CMT_MOVED_TO
UNLOCK_ABORT UNLOCK_ABORT
THROW_ERROR THROW_ERROR
...@@ -231,6 +237,13 @@ use constant LIST_OF_BUGS => 1; ...@@ -231,6 +237,13 @@ use constant LIST_OF_BUGS => 1;
# The column length for displayed (and wrapped) bug comments. # The column length for displayed (and wrapped) bug comments.
use constant COMMENT_COLS => 80; use constant COMMENT_COLS => 80;
# The type of bug comments.
use constant CMT_NORMAL => 0;
use constant CMT_DUPE_OF => 1;
use constant CMT_HAS_DUPE => 2;
use constant CMT_POPULAR_VOTES => 3;
use constant CMT_MOVED_TO => 4;
# used by Bugzilla::DB to indicate that tables are being unlocked # used by Bugzilla::DB to indicate that tables are being unlocked
# because of error # because of error
use constant UNLOCK_ABORT => 1; use constant UNLOCK_ABORT => 1;
......
...@@ -276,6 +276,9 @@ use constant ABSTRACT_SCHEMA => { ...@@ -276,6 +276,9 @@ use constant ABSTRACT_SCHEMA => {
DEFAULT => 'FALSE'}, DEFAULT => 'FALSE'},
already_wrapped => {TYPE => 'BOOLEAN', NOTNULL => 1, already_wrapped => {TYPE => 'BOOLEAN', NOTNULL => 1,
DEFAULT => 'FALSE'}, DEFAULT => 'FALSE'},
type => {TYPE => 'INT2', NOTNULL => 1,
DEFAULT => '0'},
extra_data => {TYPE => 'varchar(255)'}
], ],
INDEXES => [ INDEXES => [
longdescs_bug_id_idx => ['bug_id'], longdescs_bug_id_idx => ['bug_id'],
......
...@@ -509,6 +509,11 @@ sub update_table_definitions { ...@@ -509,6 +509,11 @@ sub update_table_definitions {
$dbh->bz_add_column('group_control_map', 'canconfirm', $dbh->bz_add_column('group_control_map', 'canconfirm',
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'}); {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
# 2006-11-07 LpSolit@gmail.com - Bug 353656
$dbh->bz_add_column('longdescs', 'type',
{TYPE => 'INT2', NOTNULL => 1, DEFAULT => '0'});
$dbh->bz_add_column('longdescs', 'extra_data', {TYPE => 'varchar(255)'});
################################################################ ################################################################
# New --TABLE-- changes should go *** A B O V E *** this point # # New --TABLE-- changes should go *** A B O V E *** this point #
################################################################ ################################################################
......
...@@ -549,13 +549,8 @@ if ($action eq Bugzilla->params->{'move-button-text'}) { ...@@ -549,13 +549,8 @@ if ($action eq Bugzilla->params->{'move-button-text'}) {
my $comment = ""; my $comment = "";
if (defined $cgi->param('comment') && $cgi->param('comment') !~ /^\s*$/) { if (defined $cgi->param('comment') && $cgi->param('comment') !~ /^\s*$/) {
$comment = $cgi->param('comment') . "\n\n"; $comment = $cgi->param('comment');
} }
$comment .= "Bug moved to " . Bugzilla->params->{'move-to-url'} . ".\n\n";
$comment .= "If the move succeeded, " . $user->login . " will receive a mail\n";
$comment .= "containing the number of the new bug in the other database.\n";
$comment .= "If all went well, please mark this bug verified, and paste\n";
$comment .= "in a link to the new bug. Otherwise, reopen this bug.\n";
$dbh->bz_lock_tables('bugs WRITE', 'bugs_activity WRITE', 'duplicates WRITE', $dbh->bz_lock_tables('bugs WRITE', 'bugs_activity WRITE', 'duplicates WRITE',
'longdescs WRITE', 'profiles READ', 'groups READ', 'longdescs WRITE', 'profiles READ', 'groups READ',
...@@ -574,7 +569,7 @@ if ($action eq Bugzilla->params->{'move-button-text'}) { ...@@ -574,7 +569,7 @@ if ($action eq Bugzilla->params->{'move-button-text'}) {
$sth->execute($timestamp, $id); $sth->execute($timestamp, $id);
$sth2->execute($id); $sth2->execute($id);
AppendComment($id, $whoid, $comment, 0, $timestamp); AppendComment($id, $whoid, $comment, 0, $timestamp, 0, CMT_MOVED_TO, $user->login);
if ($bug->bug_status ne 'RESOLVED') { if ($bug->bug_status ne 'RESOLVED') {
LogActivityEntry($id, 'bug_status', $bug->bug_status, LogActivityEntry($id, 'bug_status', $bug->bug_status,
...@@ -942,7 +937,7 @@ if ( defined $cgi->param('id') && ...@@ -942,7 +937,7 @@ if ( defined $cgi->param('id') &&
} }
} }
my $duplicate = 0; my $duplicate;
# We need to check the addresses involved in a CC change before we touch any bugs. # We need to check the addresses involved in a CC change before we touch any bugs.
# What we'll do here is formulate the CC data into two hashes of ID's involved # What we'll do here is formulate the CC data into two hashes of ID's involved
...@@ -1190,10 +1185,6 @@ SWITCH: for ($cgi->param('knob')) { ...@@ -1190,10 +1185,6 @@ SWITCH: for ($cgi->param('knob')) {
ChangeStatus('RESOLVED'); ChangeStatus('RESOLVED');
ChangeResolution($bug, 'DUPLICATE'); ChangeResolution($bug, 'DUPLICATE');
my $comment = $cgi->param('comment');
$comment .= "\n\n"
. get_text('bug_duplicate_of', { dupe_of => $duplicate });
$cgi->param('comment', $comment);
last SWITCH; last SWITCH;
}; };
...@@ -1605,9 +1596,12 @@ foreach my $id (@idlist) { ...@@ -1605,9 +1596,12 @@ foreach my $id (@idlist) {
} }
} }
if ($cgi->param('comment') || $work_time) { if ($cgi->param('comment') || $work_time || $duplicate) {
my $type = $duplicate ? CMT_DUPE_OF : CMT_NORMAL;
AppendComment($id, $whoid, scalar($cgi->param('comment')), AppendComment($id, $whoid, scalar($cgi->param('comment')),
scalar($cgi->param('commentprivacy')), $timestamp, $work_time); scalar($cgi->param('commentprivacy')), $timestamp,
$work_time, $type, $duplicate);
$bug_changed = 1; $bug_changed = 1;
} }
...@@ -2082,10 +2076,9 @@ foreach my $id (@idlist) { ...@@ -2082,10 +2076,9 @@ foreach my $id (@idlist) {
$dbh->do(q{INSERT INTO cc (who, bug_id) VALUES (?, ?)}, $dbh->do(q{INSERT INTO cc (who, bug_id) VALUES (?, ?)},
undef, $reporter, $duplicate); undef, $reporter, $duplicate);
} }
my $dupe_comment = get_text('bug_has_duplicate',
{ dupe => $cgi->param('id') });
# Bug 171639 - Duplicate notifications do not need to be private. # Bug 171639 - Duplicate notifications do not need to be private.
AppendComment($duplicate, $whoid, $dupe_comment, 0, $timestamp); AppendComment($duplicate, $whoid, "", 0, $timestamp, 0,
CMT_HAS_DUPE, scalar $cgi->param('id'));
$dbh->do(q{INSERT INTO duplicates VALUES (?, ?)}, undef, $dbh->do(q{INSERT INTO duplicates VALUES (?, ?)}, undef,
$duplicate, $cgi->param('id')); $duplicate, $cgi->param('id'));
......
...@@ -121,12 +121,22 @@ ...@@ -121,12 +121,22 @@
Please add your attachment by clicking the "Create a New Attachment" link Please add your attachment by clicking the "Create a New Attachment" link
below. below.
[% ELSIF message_tag == "bug_confirmed_by_votes" %]
*** This [% terms.bug %] has been confirmed by popular vote. ***
[% ELSIF message_tag == "bug_duplicate_of" %] [% ELSIF message_tag == "bug_duplicate_of" %]
*** This [% terms.bug %] has been marked as a duplicate of [% terms.bug %] [%+ dupe_of FILTER html %] *** *** This [% terms.bug %] has been marked as a duplicate of [% terms.bug %] [%+ dupe_of FILTER html %] ***
[% ELSIF message_tag == "bug_has_duplicate" %] [% ELSIF message_tag == "bug_has_duplicate" %]
*** [% terms.Bug %] [%+ dupe FILTER html %] has been marked as a duplicate of this [% terms.bug %]. *** *** [% terms.Bug %] [%+ dupe FILTER html %] has been marked as a duplicate of this [% terms.bug %]. ***
[% ELSIF message_tag == "bug_moved_to" %]
<p>[% terms.Bug %] moved to [% Param("move-to-url") FILTER html %].</p>
<p>If the move succeeded, [% login FILTER html %] will receive a mail
containing the number of the new [% terms.bug %] in the other database.
If all went well, please mark this [% terms.bug %] verified, and paste
in a link to the new [% terms.bug %]. Otherwise, reopen this [% terms.bug %].
[% ELSIF message_tag == "buglist_adding_field" %] [% ELSIF message_tag == "buglist_adding_field" %]
[% title = "Adding field to search page..." %] [% title = "Adding field to search page..." %]
[% link = "Click here if the page does not redisplay automatically." %] [% link = "Click here if the page does not redisplay automatically." %]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment