Commit 882dcc87 authored by gerv%gerv.net's avatar gerv%gerv.net

Bug 73665 - migrate email preferences to their own table, and rearchitect email…

Bug 73665 - migrate email preferences to their own table, and rearchitect email internals. Patch by gerv; r=jake, a=justdave.
parent 13e55e5e
...@@ -51,9 +51,6 @@ use base qw(Exporter); ...@@ -51,9 +51,6 @@ use base qw(Exporter);
LOGOUT_CURRENT LOGOUT_CURRENT
LOGOUT_KEEP_CURRENT LOGOUT_KEEP_CURRENT
DEFAULT_FLAG_EMAIL_SETTINGS
DEFAULT_EMAIL_SETTINGS
GRANT_DIRECT GRANT_DIRECT
GRANT_DERIVED GRANT_DERIVED
GRANT_REGEXP GRANT_REGEXP
...@@ -71,6 +68,20 @@ use base qw(Exporter); ...@@ -71,6 +68,20 @@ use base qw(Exporter);
COMMENT_COLS COMMENT_COLS
UNLOCK_ABORT UNLOCK_ABORT
RELATIONSHIPS
REL_ASSIGNEE REL_QA REL_REPORTER REL_CC REL_VOTER
REL_ANY
POS_EVENTS
EVT_OTHER EVT_ADDED_REMOVED EVT_COMMENT EVT_ATTACHMENT EVT_ATTACHMENT_DATA
EVT_PROJ_MANAGEMENT EVT_OPENED_CLOSED EVT_KEYWORD EVT_CC
NEG_EVENTS
EVT_UNCONFIRMED EVT_CHANGED_BY_ME
GLOBAL_EVENTS
EVT_FLAG_REQUESTED EVT_REQUESTED_FLAG
); );
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes); @Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
...@@ -136,72 +147,6 @@ use constant contenttypes => ...@@ -136,72 +147,6 @@ use constant contenttypes =>
"ics" => "text/calendar" , "ics" => "text/calendar" ,
}; };
use constant DEFAULT_FLAG_EMAIL_SETTINGS =>
"~FlagRequestee~on" .
"~FlagRequester~on";
# By default, almost all bugmail is turned on, with the exception
# of CC list additions for anyone except the Assignee/Owner.
# If you want to customize the default settings for new users at
# your own site, ensure that each of the lines ends with either
# "~on" or just "~" (for off).
use constant DEFAULT_EMAIL_SETTINGS =>
"ExcludeSelf~on" .
"~FlagRequestee~on" .
"~FlagRequester~on" .
"~emailOwnerRemoveme~on" .
"~emailOwnerComments~on" .
"~emailOwnerAttachments~on" .
"~emailOwnerStatus~on" .
"~emailOwnerResolved~on" .
"~emailOwnerKeywords~on" .
"~emailOwnerCC~on" .
"~emailOwnerOther~on" .
"~emailOwnerUnconfirmed~on" .
"~emailReporterRemoveme~on" .
"~emailReporterComments~on" .
"~emailReporterAttachments~on" .
"~emailReporterStatus~on" .
"~emailReporterResolved~on" .
"~emailReporterKeywords~on" .
"~emailReporterCC~" .
"~emailReporterOther~on" .
"~emailReporterUnconfirmed~on" .
"~emailQAcontactRemoveme~on" .
"~emailQAcontactComments~on" .
"~emailQAcontactAttachments~on" .
"~emailQAcontactStatus~on" .
"~emailQAcontactResolved~on" .
"~emailQAcontactKeywords~on" .
"~emailQAcontactCC~" .
"~emailQAcontactOther~on" .
"~emailQAcontactUnconfirmed~on" .
"~emailCClistRemoveme~on" .
"~emailCClistComments~on" .
"~emailCClistAttachments~on" .
"~emailCClistStatus~on" .
"~emailCClistResolved~on" .
"~emailCClistKeywords~on" .
"~emailCClistCC~" .
"~emailCClistOther~on" .
"~emailCClistUnconfirmed~on" .
"~emailVoterRemoveme~on" .
"~emailVoterComments~" .
"~emailVoterAttachments~" .
"~emailVoterStatus~" .
"~emailVoterResolved~on" .
"~emailVoterKeywords~" .
"~emailVoterCC~" .
"~emailVoterOther~" .
"~emailVoterUnconfirmed~";
use constant GRANT_DIRECT => 0; use constant GRANT_DIRECT => 0;
use constant GRANT_DERIVED => 1; use constant GRANT_DERIVED => 1;
use constant GRANT_REGEXP => 2; use constant GRANT_REGEXP => 2;
...@@ -230,4 +175,50 @@ use constant COMMENT_COLS => 80; ...@@ -230,4 +175,50 @@ use constant COMMENT_COLS => 80;
# because of error # because of error
use constant UNLOCK_ABORT => 1; use constant UNLOCK_ABORT => 1;
use constant REL_ASSIGNEE => 0;
use constant REL_QA => 1;
use constant REL_REPORTER => 2;
use constant REL_CC => 3;
use constant REL_VOTER => 4;
use constant RELATIONSHIPS => REL_ASSIGNEE, REL_QA, REL_REPORTER, REL_CC,
REL_VOTER;
# Used for global events like EVT_FLAG_REQUESTED
use constant REL_ANY => 100;
# There are two sorts of event - positive and negative. Positive events are
# those for which the user says "I want mail if this happens." Negative events
# are those for which the user says "I don't want mail if this happens."
#
# Exactly when each event fires is defined in wants_bug_mail() in User.pm; I'm
# not commenting them here in case the comments and the code get out of sync.
use constant EVT_OTHER => 0;
use constant EVT_ADDED_REMOVED => 1;
use constant EVT_COMMENT => 2;
use constant EVT_ATTACHMENT => 3;
use constant EVT_ATTACHMENT_DATA => 4;
use constant EVT_PROJ_MANAGEMENT => 5;
use constant EVT_OPENED_CLOSED => 6;
use constant EVT_KEYWORD => 7;
use constant EVT_CC => 8;
use constant POS_EVENTS => EVT_OTHER, EVT_ADDED_REMOVED, EVT_COMMENT,
EVT_ATTACHMENT, EVT_ATTACHMENT_DATA,
EVT_PROJ_MANAGEMENT, EVT_OPENED_CLOSED, EVT_KEYWORD,
EVT_CC;
use constant EVT_UNCONFIRMED => 50;
use constant EVT_CHANGED_BY_ME => 51;
use constant NEG_EVENTS => EVT_UNCONFIRMED, EVT_CHANGED_BY_ME;
# These are the "global" flags, which aren't tied to a particular relationship.
# and so use REL_ANY.
use constant EVT_FLAG_REQUESTED => 100; # Flag has been requested of me
use constant EVT_REQUESTED_FLAG => 101; # I have requested a flag
use constant GLOBAL_EVENTS => EVT_FLAG_REQUESTED, EVT_REQUESTED_FLAG;
1; 1;
...@@ -584,7 +584,6 @@ use constant ABSTRACT_SCHEMA => { ...@@ -584,7 +584,6 @@ use constant ABSTRACT_SCHEMA => {
disabledtext => {TYPE => 'MEDIUMTEXT', NOTNULL => 1}, disabledtext => {TYPE => 'MEDIUMTEXT', NOTNULL => 1},
mybugslink => {TYPE => 'BOOLEAN', NOTNULL => 1, mybugslink => {TYPE => 'BOOLEAN', NOTNULL => 1,
DEFAULT => 'TRUE'}, DEFAULT => 'TRUE'},
emailflags => {TYPE => 'MEDIUMTEXT'},
refreshed_when => {TYPE => 'DATETIME', NOTNULL => 1}, refreshed_when => {TYPE => 'DATETIME', NOTNULL => 1},
extern_id => {TYPE => 'varchar(64)'}, extern_id => {TYPE => 'varchar(64)'},
], ],
...@@ -610,6 +609,20 @@ use constant ABSTRACT_SCHEMA => { ...@@ -610,6 +609,20 @@ use constant ABSTRACT_SCHEMA => {
], ],
}, },
email_setting => {
FIELDS => [
user_id => {TYPE => 'INT3', NOTNULL => 1},
relationship => {TYPE => 'INT1', NOTNULL => 1},
event => {TYPE => 'INT1', NOTNULL => 1},
],
INDEXES => [
email_settings_user_id_idx => ['user_id'],
email_settings_unique_idx =>
{FIELDS => [qw(user_id relationship event)],
TYPE => 'UNIQUE'},
],
},
watch => { watch => {
FIELDS => [ FIELDS => [
watcher => {TYPE => 'INT3', NOTNULL => 1}, watcher => {TYPE => 'INT3', NOTNULL => 1},
......
...@@ -72,6 +72,7 @@ use Bugzilla::Util; ...@@ -72,6 +72,7 @@ use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
use Bugzilla::Attachment; use Bugzilla::Attachment;
use Bugzilla::BugMail; use Bugzilla::BugMail;
use Bugzilla::Constants;
use constant TABLES_ALREADY_LOCKED => 1; use constant TABLES_ALREADY_LOCKED => 1;
...@@ -482,7 +483,7 @@ sub create { ...@@ -482,7 +483,7 @@ sub create {
# Send an email notifying the relevant parties about the flag creation. # Send an email notifying the relevant parties about the flag creation.
if (($flag->{'requestee'} if (($flag->{'requestee'}
&& $flag->{'requestee'}->email_prefs->{'FlagRequestee'}) && $flag->{'requestee'}->wants_mail([EVT_FLAG_REQUESTED]))
|| $flag->{'type'}->{'cc_list'}) || $flag->{'type'}->{'cc_list'})
{ {
notify($flag, "request/email.txt.tmpl"); notify($flag, "request/email.txt.tmpl");
...@@ -590,7 +591,7 @@ sub modify { ...@@ -590,7 +591,7 @@ sub modify {
WHERE id = $flag->{'id'}"); WHERE id = $flag->{'id'}");
# Send an email notifying the relevant parties about the fulfillment. # Send an email notifying the relevant parties about the fulfillment.
if ($flag->{'setter'}->email_prefs->{'FlagRequester'} if ($flag->{'setter'}->wants_mail([EVT_REQUESTED_FLAG])
|| $flag->{'type'}->{'cc_list'}) || $flag->{'type'}->{'cc_list'})
{ {
$flag->{'status'} = $status; $flag->{'status'} = $status;
...@@ -616,7 +617,7 @@ sub modify { ...@@ -616,7 +617,7 @@ sub modify {
# Send an email notifying the relevant parties about the request. # Send an email notifying the relevant parties about the request.
if ($flag->{'requestee'} if ($flag->{'requestee'}
&& ($flag->{'requestee'}->email_prefs->{'FlagRequestee'} && ($flag->{'requestee'}->wants_mail([EVT_FLAG_REQUESTED])
|| $flag->{'type'}->{'cc_list'})) || $flag->{'type'}->{'cc_list'}))
{ {
notify($flag, "request/email.txt.tmpl"); notify($flag, "request/email.txt.tmpl");
......
...@@ -2485,7 +2485,8 @@ if (!($sth->fetchrow_arrayref()->[0])) { ...@@ -2485,7 +2485,8 @@ if (!($sth->fetchrow_arrayref()->[0])) {
# 2000-12-18. Added an 'emailflags' field for storing preferences about # 2000-12-18. Added an 'emailflags' field for storing preferences about
# when email gets sent on a per-user basis. # when email gets sent on a per-user basis.
if (!$dbh->bz_get_field_def('profiles', 'emailflags')) { if (!$dbh->bz_get_field_def('profiles', 'emailflags') &&
!$dbh->bz_get_field_def('email_setting', 'user_id')) {
$dbh->bz_add_field('profiles', 'emailflags', 'mediumtext'); $dbh->bz_add_field('profiles', 'emailflags', 'mediumtext');
} }
...@@ -3756,47 +3757,6 @@ if ($dbh->bz_get_field_def('bugs', 'short_desc')->[2]) { # if it allows nulls ...@@ -3756,47 +3757,6 @@ if ($dbh->bz_get_field_def('bugs', 'short_desc')->[2]) { # if it allows nulls
$dbh->bz_change_field_type('bugs', 'short_desc', 'mediumtext not null'); $dbh->bz_change_field_type('bugs', 'short_desc', 'mediumtext not null');
} }
# 2004-12-29 - Flag email code is broke somewhere, and doesn't treat a lack
# of FlagRequestee/er emailflags as 'on' like it's supposed to. Easiest way
# to fix this is to make sure that everyone has these set. (bug 275599).
# While we're at it, let's make sure everyone has some emailprefs set,
# whether or not they've ever visited userprefs.cgi (bug 108870). In fact,
# do this first so that the second check gets fewer hits.
#
my $emailflags_count = 0;
$sth = $dbh->prepare("SELECT userid FROM profiles " .
"WHERE emailflags LIKE '' " .
"OR emailflags IS NULL");
$sth->execute();
while (my ($userid) = $sth->fetchrow_array()) {
$dbh->do("UPDATE profiles SET emailflags = " .
$dbh->quote(Bugzilla::Constants::DEFAULT_EMAIL_SETTINGS) .
"WHERE userid = $userid");
$emailflags_count++;
}
if ($emailflags_count) {
print "Added default email prefs to $emailflags_count users who had none.\n" unless $silent;
$emailflags_count = 0;
}
$sth = $dbh->prepare("SELECT userid, emailflags FROM profiles " .
"WHERE emailflags NOT LIKE '%Flagrequeste%' ");
$sth->execute();
while (my ($userid, $emailflags) = $sth->fetchrow_array()) {
$emailflags .= Bugzilla::Constants::DEFAULT_FLAG_EMAIL_SETTINGS;
$emailflags = $dbh->quote($emailflags);
$dbh->do("UPDATE profiles SET emailflags = $emailflags " .
"WHERE userid = $userid");
$emailflags_count++;
}
if ($emailflags_count) {
print "Added default Flagrequester/ee email prefs to $emailflags_count users who had none.\n" unless $silent;
$emailflags_count = 0;
}
# 2003-10-24 - alt@sonic.net, bug 224208 # 2003-10-24 - alt@sonic.net, bug 224208
# Support classification level # Support classification level
$dbh->bz_add_field('products', 'classification_id', 'smallint DEFAULT 1'); $dbh->bz_add_field('products', 'classification_id', 'smallint DEFAULT 1');
...@@ -3882,8 +3842,113 @@ if (!$dbh->bz_get_field_def('bugs', 'qa_contact')->[2]) { # if it's NOT NULL ...@@ -3882,8 +3842,113 @@ if (!$dbh->bz_get_field_def('bugs', 'qa_contact')->[2]) { # if it's NOT NULL
WHERE initialqacontact = 0"); WHERE initialqacontact = 0");
} }
} # END LEGACY CHECKS # 2005-03-29 - gerv@gerv.net - bug 73665.
# Migrate email preferences to new email prefs table.
if ($dbh->bz_get_field_def("profiles", "emailflags")) {
print "Migrating email preferences to new table ...\n" unless $silent;
# These are the "roles" and "reasons" from the original code, mapped to
# the new terminology of relationships and events.
my %relationships = ("Owner" => REL_ASSIGNEE,
"Reporter" => REL_REPORTER,
"QAcontact" => REL_QA,
"CClist" => REL_CC,
"Voter" => REL_VOTER);
my %events = ("Removeme" => EVT_ADDED_REMOVED,
"Comments" => EVT_COMMENT,
"Attachments" => EVT_ATTACHMENT,
"Status" => EVT_PROJ_MANAGEMENT,
"Resolved" => EVT_OPENED_CLOSED,
"Keywords" => EVT_KEYWORD,
"CC" => EVT_CC,
"Other" => EVT_OTHER,
"Unconfirmed" => EVT_UNCONFIRMED);
# Request preferences
my %requestprefs = ("FlagRequestee" => EVT_FLAG_REQUESTED,
"FlagRequester" => EVT_REQUESTED_FLAG);
# Select all emailflags flag strings
my $sth = $dbh->prepare("SELECT userid, emailflags FROM profiles");
$sth->execute();
while (my ($userid, $flagstring) = $sth->fetchrow_array()) {
# If the user has never logged in since emailprefs arrived, and the
# temporary code to give them a default string never ran, then
# $flagstring will be null. In this case, they just get all mail.
$flagstring ||= "";
# The 255 param is here, because without a third param, split will
# trim any trailing null fields, which causes Perl to eject lots of
# warnings. Any suitably large number would do.
my %emailflags = split(/~/, $flagstring, 255); # Appease my editor: /
my $sth2 = $dbh->prepare("INSERT into email_setting " .
"(user_id, relationship, event) VALUES (" .
"$userid, ?, ?)");
foreach my $relationship (keys %relationships) {
foreach my $event (keys %events) {
my $key = "email$relationship$event";
if (!exists($emailflags{$key}) || $emailflags{$key} eq 'on') {
$sth2->execute($relationships{$relationship},
$events{$event});
}
}
}
# Note that in the old system, the value of "excludeself" is assumed to
# be off if the preference does not exist in the user's list, unlike
# other preferences whose value is assumed to be on if they do not
# exist.
#
# This preference has changed from global to per-relationship.
if (!exists($emailflags{'ExcludeSelf'})
|| $emailflags{'ExcludeSelf'} ne 'on')
{
foreach my $relationship (keys %relationships) {
$dbh->do("INSERT into email_setting " .
"(user_id, relationship, event) VALUES (" .
$userid . ", " .
$relationships{$relationship}. ", " .
EVT_CHANGED_BY_ME . ")");
}
}
foreach my $key (keys %requestprefs) {
if (!exists($emailflags{$key}) || $emailflags{$key} eq 'on') {
$dbh->do("INSERT into email_setting " .
"(user_id, relationship, event) VALUES (" .
$userid . ", " . REL_ANY . ", " .
$requestprefs{$key} . ")");
}
}
}
# EVT_ATTACHMENT_DATA should initially have identical settings to
# EVT_ATTACHMENT.
CloneEmailEvent(EVT_ATTACHMENT, EVT_ATTACHMENT_DATA);
$dbh->bz_drop_field("profiles", "emailflags");
}
sub CloneEmailEvent {
my ($source, $target) = @_;
my $sth1 = $dbh->prepare("SELECT user_id, relationship FROM email_setting
WHERE event = $source");
my $sth2 = $dbh->prepare("INSERT into email_setting " .
"(user_id, relationship, event) VALUES (" .
"?, ?, $target)");
$sth1->execute();
while (my ($userid, $relationship) = $sth1->fetchrow_array()) {
$sth2->execute($userid, $relationship);
}
}
} # END LEGACY CHECKS
# If you had to change the --TABLE-- definition in any way, then add your # If you had to change the --TABLE-- definition in any way, then add your
# differential change code *** A B O V E *** this comment. # differential change code *** A B O V E *** this comment.
...@@ -4156,10 +4221,10 @@ if ($sth->rows == 0) { ...@@ -4156,10 +4221,10 @@ if ($sth->rows == 0) {
$dbh->do( $dbh->do(
q{INSERT INTO profiles (login_name, realname, cryptpassword, q{INSERT INTO profiles (login_name, realname, cryptpassword,
emailflags, disabledtext, refreshed_when) disabledtext, refreshed_when)
VALUES (?, ?, ?, ?, ?, ?)}, VALUES (?, ?, ?, ?, ?, ?)},
undef, $login, $realname, $cryptedpassword, undef, $login, $realname, $cryptedpassword,
Bugzilla::Constants::DEFAULT_EMAIL_SETTINGS, '', '1900-01-01 00:00:00'); '', '1900-01-01 00:00:00');
} }
# Put the admin in each group if not already # Put the admin in each group if not already
......
...@@ -47,9 +47,22 @@ if (scalar(@list) > 0) { ...@@ -47,9 +47,22 @@ if (scalar(@list) > 0) {
my $start_time = time; my $start_time = time;
print "Sending mail for bug $bugid...\n"; print "Sending mail for bug $bugid...\n";
my $outputref = Bugzilla::BugMail::Send($bugid); my $outputref = Bugzilla::BugMail::Send($bugid);
my ($sent, $excluded) = (scalar(@{$outputref->{sent}}),scalar(@{$outputref->{excluded}})); if ($ARGV[0] && $ARGV[0] eq "--report") {
print "$sent mails sent, $excluded people excluded.\n"; print "Mail sent to:\n";
print "Took " . (time - $start_time) . " seconds.\n\n"; foreach (sort @{$outputref->{sent}}) {
print $_ . "\n";
}
print "Excluded:\n";
foreach (sort @{$outputref->{excluded}}) {
print $_ . "\n";
}
}
else {
my ($sent, $excluded) = (scalar(@{$outputref->{sent}}),scalar(@{$outputref->{excluded}}));
print "$sent mails sent, $excluded people excluded.\n";
print "Took " . (time - $start_time) . " seconds.\n\n";
}
} }
print "Unsent mail has been sent.\n"; print "Unsent mail has been sent.\n";
} }
...@@ -486,14 +486,7 @@ if (UserInGroup("editbugs")) { ...@@ -486,14 +486,7 @@ if (UserInGroup("editbugs")) {
} }
# Email everyone the details of the new bug # Email everyone the details of the new bug
$vars->{'mailrecipients'} = { 'cc' => \@cc, $vars->{'mailrecipients'} = {'changer' => Bugzilla->user->login};
'owner' => DBID_to_name($::FORM{'assigned_to'}),
'reporter' => Bugzilla->user->login,
'changer' => Bugzilla->user->login };
if (defined $::FORM{'qa_contact'}) {
$vars->{'mailrecipients'}->{'qacontact'} = DBID_to_name($::FORM{'qa_contact'});
}
$vars->{'id'} = $id; $vars->{'id'} = $id;
my $bug = new Bugzilla::Bug($id, $::userid); my $bug = new Bugzilla::Bug($id, $::userid);
......
...@@ -645,9 +645,9 @@ ...@@ -645,9 +645,9 @@
], ],
'account/prefs/email.html.tmpl' => [ 'account/prefs/email.html.tmpl' => [
'role', 'relationship.id',
'reason.name', 'event.id',
'reason.description', 'prefname',
], ],
'account/prefs/permissions.html.tmpl' => [ 'account/prefs/permissions.html.tmpl' => [
......
...@@ -28,11 +28,13 @@ ...@@ -28,11 +28,13 @@
[% statuses = { '+' => "granted" , '-' => 'denied' , 'X' => "cancelled" , [% statuses = { '+' => "granted" , '-' => 'denied' , 'X' => "cancelled" ,
'?' => "asked" } %] '?' => "asked" } %]
[% IF flag.status == '?' %] [% IF flag.status == '?' %]
[% to_email = flag.requestee.email IF flag.requestee.email_prefs.FlagRequestee %] [% to_email = flag.requestee.email
IF flag.requestee.wants_mail(constants.EVT_FLAG_REQUESTED) %]
[% to_identity = flag.requestee.identity %] [% to_identity = flag.requestee.identity %]
[% subject_status = "requested" %] [% subject_status = "requested" %]
[% ELSE %] [% ELSE %]
[% to_email = flag.setter.email IF flag.setter.email_prefs.FlagRequester %] [% to_email = flag.setter.email
IF flag.setter.wants_mail(constants.EVT_REQUESTED_FLAG) %]
[% to_identity = flag.setter.identity _ "'s request" %] [% to_identity = flag.setter.identity _ "'s request" %]
[% subject_status = statuses.${flag.status} %] [% subject_status = statuses.${flag.status} %]
[% END %] [% END %]
......
...@@ -37,10 +37,6 @@ require "CGI.pl"; ...@@ -37,10 +37,6 @@ require "CGI.pl";
# Use global template variables. # Use global template variables.
use vars qw($template $vars $userid); use vars qw($template $vars $userid);
my @roles = ("Owner", "Reporter", "QAcontact", "CClist", "Voter");
my @reasons = ("Removeme", "Comments", "Attachments", "Status", "Resolved",
"Keywords", "CC", "Other", "Unconfirmed");
############################################################################### ###############################################################################
# Each panel has two functions - panel Foo has a DoFoo, to get the data # Each panel has two functions - panel Foo has a DoFoo, to get the data
# necessary for displaying the panel, and a SaveFoo, to save the panel's # necessary for displaying the panel, and a SaveFoo, to save the panel's
...@@ -175,7 +171,10 @@ sub SaveSettings { ...@@ -175,7 +171,10 @@ sub SaveSettings {
sub DoEmail { sub DoEmail {
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
###########################################################################
# User watching
###########################################################################
if (Param("supportwatchers")) { if (Param("supportwatchers")) {
my $watched_ref = $dbh->selectcol_arrayref( my $watched_ref = $dbh->selectcol_arrayref(
"SELECT profiles.login_name FROM watch, profiles" "SELECT profiles.login_name FROM watch, profiles"
...@@ -197,81 +196,74 @@ sub DoEmail { ...@@ -197,81 +196,74 @@ sub DoEmail {
$vars->{'watchers'} = \@watchers; $vars->{'watchers'} = \@watchers;
} }
SendSQL("SELECT emailflags FROM profiles WHERE userid = $userid"); ###########################################################################
# Role-based preferences
my ($flagstring) = FetchSQLData(); ###########################################################################
my $sth = Bugzilla->dbh->prepare("SELECT relationship, event " .
"FROM email_setting " .
"WHERE user_id = $userid");
$sth->execute();
my %mail;
while (my ($relationship, $event) = $sth->fetchrow_array()) {
$mail{$relationship}{$event} = 1;
}
# The 255 param is here, because without a third param, split will $vars->{'mail'} = \%mail;
# trim any trailing null fields, which causes Perl to eject lots of }
# warnings. Any suitably large number would do.
my %emailflags = split(/~/, $flagstring, 255);
# Determine the value of the "excludeself" global email preference. sub SaveEmail {
# Note that the value of "excludeself" is assumed to be off if the my $dbh = Bugzilla->dbh;
# preference does not exist in the user's list, unlike other my $cgi = Bugzilla->cgi;
# preferences whose value is assumed to be on if they do not exist.
if (exists($emailflags{'ExcludeSelf'})
&& $emailflags{'ExcludeSelf'} eq 'on')
{
$vars->{'excludeself'} = 1;
}
else {
$vars->{'excludeself'} = 0;
}
foreach my $flag (qw(FlagRequestee FlagRequester)) {
$vars->{$flag} =
!exists($emailflags{$flag}) || $emailflags{$flag} eq 'on';
}
# Parse the info into a hash of hashes; the first hash keyed by role, ###########################################################################
# the second by reason, and the value being 1 or 0 for (on or off). # Role-based preferences
# Preferences not existing in the user's list are assumed to be on. ###########################################################################
foreach my $role (@roles) { $dbh->bz_lock_tables("email_setting WRITE");
$vars->{$role} = {};
foreach my $reason (@reasons) { # Delete all the user's current preferences
my $key = "email$role$reason"; $dbh->do("DELETE FROM email_setting WHERE user_id = $userid");
if (!exists($emailflags{$key}) || $emailflags{$key} eq 'on') {
$vars->{$role}{$reason} = 1; # Repopulate the table - first, with normal events in the
# relationship/event matrix.
# Note: the database holds only "off" email preferences, as can be implied
# from the name of the table - profiles_nomail.
foreach my $rel (RELATIONSHIPS) {
# Positive events: a ticked box means "send me mail."
foreach my $event (POS_EVENTS) {
if (1 == $cgi->param("email-$rel-$event")) {
$dbh->do("INSERT INTO email_setting " .
"(user_id, relationship, event) " .
"VALUES ($userid, $rel, $event)");
} }
else { }
$vars->{$role}{$reason} = 0;
# Negative events: a ticked box means "don't send me mail."
foreach my $event (NEG_EVENTS) {
if (!defined($cgi->param("neg-email-$rel-$event")) ||
$cgi->param("neg-email-$rel-$event") != 1)
{
$dbh->do("INSERT INTO email_setting " .
"(user_id, relationship, event) " .
"VALUES ($userid, $rel, $event)");
} }
} }
} }
}
# Note: we no longer store "off" values in the database.
sub SaveEmail {
my $updateString = "";
my $cgi = Bugzilla->cgi;
my $dbh = Bugzilla->dbh;
if (defined $cgi->param('ExcludeSelf')) { # Global positive events: a ticked box means "send me mail."
$updateString .= 'ExcludeSelf~on'; foreach my $event (GLOBAL_EVENTS) {
} else { if (1 == $cgi->param("email-" . REL_ANY . "-$event")) {
$updateString .= 'ExcludeSelf~'; $dbh->do("INSERT INTO email_setting " .
} "(user_id, relationship, event) " .
"VALUES ($userid, " . REL_ANY . ", $event)");
foreach my $flag (qw(FlagRequestee FlagRequester)) {
$updateString .= "~$flag~" . (defined $cgi->param($flag) ? "on" : "");
}
foreach my $role (@roles) {
foreach my $reason (@reasons) {
# Add this preference to the list without giving it a value,
# which is the equivalent of setting the value to "off."
$updateString .= "~email$role$reason~";
# If the form field for this preference is defined, then we
# know the checkbox was checked, so set the value to "on".
$updateString .= "on" if defined $cgi->param("email$role$reason");
} }
} }
SendSQL("UPDATE profiles SET emailflags = " . SqlQuote($updateString) .
" WHERE userid = $userid");
$dbh->bz_unlock_tables();
###########################################################################
# User watching
###########################################################################
if (Param("supportwatchers") && defined $cgi->param('watchedusers')) { if (Param("supportwatchers") && defined $cgi->param('watchedusers')) {
# Just in case. Note that this much locking is actually overkill: # Just in case. Note that this much locking is actually overkill:
# we don't really care if anyone reads the watch table. So # we don't really care if anyone reads the watch table. So
......
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