#####################################################################
sub send_changes {
- my ($self, $changes, $vars) = @_;
+ my ($self, $changes, $vars, $minor_update) = @_;
my $user = Bugzilla->user;
changer => $user,
);
- _send_bugmail({ id => $self->id, type => 'bug', forced => \%forced },
- $vars);
+ _send_bugmail({ id => $self->id, type => 'bug', forced => \%forced,
+ minor_update => $minor_update }, $vars);
# If the bug was marked as a duplicate, we need to notify users on the
# other bug of any changes to that bug.
my $new_dup_id = $changes->{'dup_id'} ? $changes->{'dup_id'}->[1] : undef;
if ($new_dup_id) {
_send_bugmail({ forced => { changer => $user }, type => "dupe",
- id => $new_dup_id }, $vars);
+ id => $new_dup_id, minor_update => $minor_update }, $vars);
}
# If there were changes in dependencies, we need to notify those
type => 'dep',
dep_only => 1,
blocker => $self,
- changes => $changes };
+ changes => $changes,
+ minor_update => $minor_update };
foreach my $id (@{ $self->blocked }) {
$params->{id} = $id;
foreach my $id (sort { $a <=> $b } (keys %changed_deps)) {
_send_bugmail({ forced => { changer => $user }, type => "dep",
- id => $id }, $vars);
+ id => $id, minor_update => $minor_update }, $vars);
}
# Sending emails for the referenced bugs.
foreach my $ref_bug_id (uniq @{ $self->{see_also_changes} || [] }) {
_send_bugmail({ forced => { changer => $user },
- id => $ref_bug_id }, $vars);
+ id => $ref_bug_id, minor_update => $minor_update }, $vars);
}
}
return(\@operations, $incomplete_data);
}
+sub has_unsent_changes {
+ my $self = shift;
+ return 1 if !defined $self->lastdiffed;
+ return datetime_from($self->lastdiffed) < datetime_from($self->delta_ts) ? 1 : 0;
+}
+
# Update the bugs_activity table to reflect changes made in bugs.
sub LogActivityEntry {
my ($bug_id, $field, $removed, $added, $user_id, $timestamp, $comment_id,
Creates or updates a L<Bugzilla::BugUserLastVisit> for this bug and the supplied
$user, the timestamp given as $last_visit.
+=item C<has_unsent_changes()>
+
+Checks if this bug has changes for which bug mail has not been sent.
+
=back
=head1 B<Methods in need of POD>
my $date = $params->{dep_only} ? $end : $bug->delta_ts;
$date = format_time($date, '%a, %d %b %Y %T %z', 'UTC');
+ my $minor_update = $changer->in_group(Bugzilla->params->{minor_update_group})
+ && $params->{minor_update};
+
foreach my $user_id (keys %recipients) {
my %rels_which_want;
my $user = $user_cache{$user_id} ||= new Bugzilla::User($user_id);
$start ? \@diffs : [],
$comments,
$params->{dep_only},
- $changer))
+ $changer,
+ $minor_update))
{
$rels_which_want{$relationship} =
$recipients{$user_id}->{$relationship};
checker => \&check_comment_taggers_group
},
+ {
+ name => 'minor_update_group',
+ type => 's',
+ choices => \&_get_all_group_names,
+ default => '',
+ checker => \&check_group
+ },
+
{
name => 'debug_group',
type => 's',
EVT_BUG_CREATED EVT_COMPONENT
NEG_EVENTS
- EVT_UNCONFIRMED EVT_CHANGED_BY_ME
+ EVT_UNCONFIRMED EVT_CHANGED_BY_ME EVT_MINOR_UPDATE
GLOBAL_EVENTS
EVT_FLAG_REQUESTED EVT_REQUESTED_FLAG
use constant EVT_UNCONFIRMED => 50;
use constant EVT_CHANGED_BY_ME => 51;
+use constant EVT_MINOR_UPDATE => 52;
-use constant NEG_EVENTS => EVT_UNCONFIRMED, EVT_CHANGED_BY_ME;
+use constant NEG_EVENTS => EVT_UNCONFIRMED, EVT_CHANGED_BY_ME, EVT_MINOR_UPDATE;
# These are the "global" flags, which aren't tied to a particular relationship.
# and so use REL_ANY.
# Note: the "+" signs before the constants suppress bareword quoting.
sub wants_bug_mail {
my $self = shift;
- my ($bug, $relationship, $fieldDiffs, $comments, $dep_mail, $changer) = @_;
+ my ($bug, $relationship, $fieldDiffs, $comments, $dep_mail, $changer,
+ $minor_update) = @_;
# Make a list of the events which have happened during this bug change,
# from the point of view of this user.
if ($wants_mail && $bug->bug_status eq 'UNCONFIRMED') {
$wants_mail &= $self->wants_mail([EVT_UNCONFIRMED], $relationship);
}
+
+ if ($wants_mail && $minor_update) {
+ $wants_mail &= $self->wants_mail([EVT_MINOR_UPDATE], $relationship);
+ }
return $wants_mail;
}
my @bugs = map { Bugzilla::Bug->check_for_edit($_) } @$ids;
+ my $minor_update = delete $params->{minor_update} ? 1 : 0;
my %values = %$params;
$values{other_bugs} = \@bugs;
}
my %all_changes;
+ my %minor_updates;
$dbh->bz_start_transaction();
foreach my $bug (@bugs) {
+ $minor_updates{$bug->id} = $bug->has_unsent_changes ? 0 : $minor_update;
$all_changes{$bug->id} = $bug->update();
}
$dbh->bz_commit_transaction();
foreach my $bug (@bugs) {
- $bug->send_changes($all_changes{$bug->id});
+ $bug->send_changes($all_changes{$bug->id}, undef, $minor_updates{$bug->id});
}
my %api_name = reverse %{ Bugzilla::Bug::FIELD_MAP() };
|| ThrowCodeError('param_required', { param => 'data' });
my @bugs = map { Bugzilla::Bug->check_for_edit($_) } @{ $params->{ids} };
+ my $minor_update = delete $params->{minor_update} ? 1 : 0;
my @created;
$dbh->bz_start_transaction();
extra_data => $attachment->id });
push(@created, $attachment);
}
- $_->bug->update($timestamp) foreach @created;
+ my %minor_updates;
+ foreach my $attachment (@created) {
+ my $bug = $attachment->bug;
+ $minor_updates{$bug->id} = $bug->has_unsent_changes ? 0 : $minor_update;
+ $bug->update($timestamp);
+ }
$dbh->bz_commit_transaction();
- $_->send_changes() foreach @bugs;
+ foreach my $bug (@bugs) {
+ $bug->send_changes(undef, undef, $minor_updates{$bug->id});
+ }
my @created_ids = map { $_->id } @created;
my $ids = delete $params->{ids};
defined $ids || ThrowCodeError('param_required', { param => 'ids' });
+ my $req_minor_update = delete $params->{minor_update} ? 1 : 0;
# Some fields cannot be sent to set_all
foreach my $key (qw(login password token)) {
delete $params->{$key};
# Email users about the change
foreach my $bug (values %bugs) {
+ my $minor_update = $bug->has_unsent_changes ? 0 : $req_minor_update;
$bug->update();
- $bug->send_changes();
+ $bug->send_changes(undef, undef, $minor_update);
}
# Return the information to the user
|| ThrowCodeError('param_required', { param => 'comment' });
my $bug = Bugzilla::Bug->check_for_edit($params->{id});
+ my $minor_update = delete $params->{minor_update} ? 1 : 0;
+ $minor_update = $bug->has_unsent_changes ? 0 : $minor_update;
# Backwards-compatibility for versions before 3.6
if (defined $params->{private}) {
my $new_comment_id = $bug->{added_comments}[0]->id;
# Send mail.
- Bugzilla::BugMail::Send($bug->bug_id, { changer => $user });
+ Bugzilla::BugMail::Send($bug->bug_id, { changer => $user },
+ { minor_update => $minor_update });
return { id => $self->type('int', $new_comment_id) };
}
my ($add, $remove) = @$params{qw(add remove)};
($add || $remove)
or ThrowCodeError('params_required', { params => ['add', 'remove'] });
+ my $req_minor_update = delete $params->{minor_update} ? 1 : 0;
my @bugs;
foreach my $id (@{ $params->{ids} }) {
my %changes;
foreach my $bug (@bugs) {
+ my $minor_update = $bug->has_unsent_changes ? 0 : $req_minor_update;
my $change = $bug->update();
if (my $see_also = $change->{see_also}) {
$changes{$bug->id}->{see_also} = {
$changes{$bug->id}->{see_also} = { added => [], removed => [] };
}
- Bugzilla::BugMail::Send($bug->id, { changer => $user });
+ Bugzilla::BugMail::Send($bug->id, { changer => $user },
+ { minor_update => $minor_update });
}
return { changes => \%changes };
=back
+=item C<minor_update>
+
+C<boolean> If set to true, this is considered a minor update and no mail is sent
+to users who do not want minor update emails. If current user is not in the
+minor_update_group, this parameter is simply ignored.
+
=back
=item B<Returns>
=back
+=item C<minor_update>
+
+C<boolean> If set to true, this is considered a minor update and no mail is sent
+to users who do not want minor update emails. If current user is not in the
+minor_update_group, this parameter is simply ignored.
+
+=back
+
=item B<Returns>
A C<hash> with a single field, "attachments". This points to an array of hashes
=back
-=back
-
=head2 add_comment
B<STABLE>
on the bug. If you are not in the time tracking group, this value will
be ignored.
+=item C<minor_update> (boolean) - If set to true, this is considered a minor update
+and no mail is sent to users who do not want minor update emails. If current user
+is not in the minor_update_group, this parameter is simply ignored.
=back
Array of C<int>s or C<string>s. The ids or aliases of the bugs that
you want to modify.
+=item C<minor_update>
+
+C<boolean> If set to true, this is considered a minor update and no mail is sent
+to users who do not want minor update emails. If current user is not in the
+minor_update_group, this parameter is simply ignored.
+
=back
B<Note>: All following fields specify the values you want to set on the
it will just be silently ignored. Invaild URLs are currently silently ignored,
though this may change in some future version of Bugzilla.
+=item C<minor_update>
+
+C<boolean> If set to true, this is considered a minor update and no mail is sent
+to users who do not want minor update emails. If current user is not in the
+minor_update_group, this parameter is simply ignored.
+
=back
NOTE: If you specify the same URL in both C<add> and C<remove>, it will
@obsolete_attachments = Bugzilla::Attachment->validate_obsolete($bug, \@obsolete);
}
+ my $minor_update = $cgi->param('minor_update') ? 1 : 0;
+ $minor_update = $bug->has_unsent_changes ? 0 : $minor_update;
+
# Must be called before create() as it may alter $cgi->param('ispatch').
my $content_type = Bugzilla::Attachment::get_content_type();
$vars->{'contenttypemethod'} = $cgi->param('contenttypemethod');
my $recipients = { 'changer' => $user, 'owner' => $owner };
- $vars->{'sent_bugmail'} = Bugzilla::BugMail::Send($bugid, $recipients);
+ my $params = { 'minor_update' => $minor_update };
+ $vars->{'sent_bugmail'} = Bugzilla::BugMail::Send($bugid, $recipients, $params);
print $cgi->header();
# Generate and return the UI (HTML page) from the appropriate template.
my $token = $cgi->param('token');
check_hash_token($token, [$attachment->id, $attachment->modification_time]);
+ my $minor_update = $cgi->param('minor_update') ? 1 : 0;
+ $minor_update = $bug->has_unsent_changes ? 0 : $minor_update;
+
# If the user submitted a comment while editing the attachment,
# add the comment to the bug. Do this after having validated isprivate!
my $comment = $cgi->param('comment');
$vars->{'bugs'} = [$bug];
$vars->{'header_done'} = 1;
$vars->{'sent_bugmail'} =
- Bugzilla::BugMail::Send($bug->id, { 'changer' => $user });
+ Bugzilla::BugMail::Send($bug->id, { 'changer' => $user },
+ {'minor_update' => $minor_update });
print $cgi->header();
##############################
# Do Actual Database Updates #
##############################
+my $req_minor_update = $cgi->param('minor_update') ? 1 : 0;
foreach my $bug (@bug_objects) {
+ my $minor_update = $bug->has_unsent_changes ? 0 : $req_minor_update;
my $changes = $bug->update();
if ($changes->{'bug_status'}) {
}
}
- $bug->send_changes($changes, $vars);
+ $bug->send_changes($changes, $vars, $minor_update);
}
# Delete the session token used for the mass-change.
.knob-buttons {
float: right;
+ text-align: right;
+ font-size: small;
+ font-weight: normal;
}
.text_input, .bz_userfield, #keywords_container, #tag_container {
description = "The $terms.bug is in the UNCONFIRMED state" },
{ id = constants.EVT_CHANGED_BY_ME,
description = "The change was made by me" },
+ { id = constants.EVT_MINOR_UPDATE,
+ description = "The change was marked as a minor update" },
] %]
[% relationships = [
%]
[% FOREACH group IN ["chartgroup", "comment_taggers_group", "debug_group",
- "insidergroup", "querysharegroup", "timetrackinggroup"] %]
+ "insidergroup", "minor_update_group", "querysharegroup",
+ "timetrackinggroup"] %]
[% special_group = Param(group) %]
[% IF special_group %]
"view it. If it is off, a user needs to be a member of all " _
"the $terms.bug's groups. Note that in either case, if the " _
"user has a role on the $terms.bug (e.g. reporter) that may " _
- "also affect their permissions."
+ "also affect their permissions.",
+
+ minor_update_group => "The name of the group of users who are allowed to " _
+ "use the 'minor update'-option on $terms.bug changes " _
+ "to limit mail sending. " _
+ "Setting this to empty disables the feature.",
}
%]
[% Hook.process('form_before_submit') %]
+ [% IF Param('minor_update_group') && user.in_group(Param('minor_update_group')) %]
+ <tr>
+ <th> </th>
+ <td>
+ <input type="checkbox" name="minor_update" value="1">
+ <label class="" for="minor_update">
+ This is a minor update (do not send email)
+ </label>
+ </td>
+ </tr>
+ [% END %]
<tr>
<th> </th>
<td><input type="submit" id="create" value="Submit"></td>
[% IF user.id %]
<div id="update_container">
+ [% IF Param('minor_update_group') && user.in_group(Param('minor_update_group')) %]
+ <input type="checkbox" name="minor_update" value="1">
+ <label class="" for="minor_update">
+ This is a minor update (do not send email)
+ </label><br>
+ [% END %]
<input type="submit" value="Submit" id="update">
</div>
[% END %]
<div class="knob-buttons">
<input type="submit" value="Save Changes"
id="commit[% id FILTER css_class_quote %]">
+ [% IF Param('minor_update_group') && user.in_group(Param('minor_update_group')) %]
+ <br>
+ <label class="" for="minor_update">
+ This is a minor update (do not send email)
+ </label>
+ <input type="checkbox" name="minor_update" value="1">
+ [% END %]
</div>
[% END %]
[% END %]
[%+ Hook.process('after_groups') %]
<input type="submit" id="commit" value="Commit">
+[% IF Param('minor_update_group') && user.in_group(Param('minor_update_group')) %]
+ <br>
+ <input type="checkbox" name="minor_update" value="1">
+ <label for="minor_update">
+ This is a minor update (do not send email)
+ </label>
+[% END %]
[%############################################################################%]
[%# Select Menu Block #%]