diff options
author | Byron Jones <glob@mozilla.com> | 2015-05-19 14:46:40 +0200 |
---|---|---|
committer | Byron Jones <glob@mozilla.com> | 2015-05-19 14:46:40 +0200 |
commit | 70b298ecbd3aba8f24bf6d0147bece13b81d6040 (patch) | |
tree | b150bd979da130f3bfc7f361730ff9f63f1baa0b | |
parent | a92ec2797af87cb17fff925ccd8c739f6d21ea79 (diff) | |
download | bugzilla-70b298ecbd3aba8f24bf6d0147bece13b81d6040.tar.gz bugzilla-70b298ecbd3aba8f24bf6d0147bece13b81d6040.tar.xz |
Bug 1163868: Include requests from others in RequestNagger
10 files changed, 570 insertions, 326 deletions
diff --git a/extensions/RequestNagger/bin/send-request-nags.pl b/extensions/RequestNagger/bin/send-request-nags.pl index 93265b9ee..1673d2208 100755 --- a/extensions/RequestNagger/bin/send-request-nags.pl +++ b/extensions/RequestNagger/bin/send-request-nags.pl @@ -19,6 +19,7 @@ BEGIN { Bugzilla->extensions() } use Bugzilla::Attachment; use Bugzilla::Bug; use Bugzilla::Constants; +use Bugzilla::Hook; use Bugzilla::Error; use Bugzilla::Extension::RequestNagger::Constants; use Bugzilla::Extension::RequestNagger::Bug; @@ -26,7 +27,7 @@ use Bugzilla::Mailer; use Bugzilla::User; use Bugzilla::Util qw(format_time); use Email::MIME; -use Sys::Hostname; +use Sys::Hostname qw(hostname); Bugzilla->usage_mode(USAGE_MODE_CMDLINE); @@ -42,168 +43,211 @@ Bugzilla->switch_to_shadow_db(); # send nags to requestees send_nags( - sql => REQUESTEE_NAG_SQL, - template => 'requestee', - recipient_field => 'requestee_id', - date => $date, + requestee_sql => REQUESTEE_NAG_SQL, + setter_sql => SETTER_NAG_SQL, + template => 'user', + date => $date, ); # send nags to watchers send_nags( - sql => WATCHING_NAG_SQL, - template => 'watching', - recipient_field => 'watcher_id', - date => $date, + requestee_sql => WATCHING_REQUESTEE_NAG_SQL, + setter_sql => WATCHING_SETTER_NAG_SQL, + template => 'watching', + date => $date, ); sub send_nags { my (%args) = @_; - my $rows = $dbh->selectall_arrayref($args{sql}, { Slice => {} }); - - # iterate over rows, sending email when the current recipient changes - my $requests = []; - my $current_recipient; - foreach my $request (@$rows) { - # send previous user's requests - if (!$current_recipient || $request->{$args{recipient_field}} != $current_recipient->id) { - send_email(%args, recipient => $current_recipient, requests => $requests); - $current_recipient = Bugzilla::User->new({ id => $request->{$args{recipient_field}}, cache => 1 }); - $requests = []; + + my @reports = qw( requestee setter ); + my $securemail = Bugzilla::User->can('public_key'); + my $requests = {}; + + # get requests + + foreach my $report (@reports) { + + # collate requests + my $rows = $dbh->selectall_arrayref($args{$report . '_sql'}, { Slice => {} }); + foreach my $request (@$rows) { + next unless _include_request($request, $report); + + my $target = Bugzilla::User->new({ id => $request->{target_id}, cache => 1 }); + push @{ + $requests + ->{$request->{recipient_id}} + ->{$target->login} + ->{$report} + ->{$request->{flag_type}} + }, $request; + push @{ + $requests + ->{$request->{recipient_id}} + ->{$target->login} + ->{bug_ids} + ->{$report} + }, $request->{bug_id}; } - # check group membership - $request->{requestee} = Bugzilla::User->new({ id => $request->{requestee_id}, cache => 1 }); - my $group; - foreach my $type (FLAG_TYPES) { - next unless $type->{type} eq $request->{flag_type}; - $group = $type->{group}; - last; + # process requests here to avoid doing it in the templates + foreach my $recipient_id (keys %$requests) { + foreach my $target_login (keys %{ $requests->{$recipient_id} }) { + my $rh = $requests->{$recipient_id}->{$target_login}; + + # build a list of valid types in the correct order + $rh->{types}->{$report} = []; + foreach my $type (map { $_->{type} } FLAG_TYPES) { + next unless exists $rh->{$report}->{$type}; + push @{ $rh->{types}->{$report} }, $type; + } + + # build a summary + $rh->{summary}->{$report} = join(', ', + map { scalar(@{ $rh->{$report}->{$_} }) . ' ' . $_ } + @{ $rh->{types}->{$report} } + ); + } } - next unless $request->{requestee}->in_group($group); - - # check bug visibility - next unless $current_recipient->can_see_bug($request->{bug_id}); - - # create objects - $request->{bug} = Bugzilla::Bug->new({ id => $request->{bug_id}, cache => 1 }); - $request->{requester} = Bugzilla::User->new({ id => $request->{requester_id}, cache => 1 }); - $request->{flag} = Bugzilla::Flag->new({ id => $request->{flag_id}, cache => 1 }); - if ($request->{attach_id}) { - $request->{attachment} = Bugzilla::Attachment->new({ id => $request->{attach_id}, cache => 1 }); - # check attachment visibility - next if $request->{attachment}->isprivate && !$current_recipient->is_insider; + } + + # send emails + + foreach my $recipient_id (sort keys %$requests) { + my $recipient = Bugzilla::User->new({ id => $recipient_id, cache => 1 }); + my $has_key = $securemail && $recipient->public_key; + my $has_private_bug = 0; + + foreach my $target_login (keys %{ $requests->{$recipient_id} }) { + my $rh = $requests->{$recipient_id}->{$target_login}; + $rh->{target} = Bugzilla::User->new({ name => $target_login, cache => 1 }); + foreach my $report (@reports) { + foreach my $type (keys %{ $rh->{$report} }) { + foreach my $request (@{ $rh->{$report}->{$type} }) { + + _create_objects($request); + + # we need to encrypt or censor emails which contain + # non-public bugs + if ($request->{bug}->is_private) { + $has_private_bug = 1; + $request->{bug}->{sanitise_bug} = !$securemail || !$has_key; + } + else { + $request->{bug}->{sanitise_bug} = 0; + } + } + } + } } - if (exists $request->{watcher_id}) { - $request->{watcher} = Bugzilla::User->new({ id => $request->{watcher_id}, cache => 1 }); + my $encrypt = $securemail && $has_private_bug && $has_key; + + # generate email + my $template = Bugzilla->template_inner($recipient->setting('lang')); + my $template_file = $args{template}; + my $vars = { + recipient => $recipient, + requests => $requests->{$recipient_id}, + date => $args{date}, + }; + + my ($header, $text); + $template->process("email/request_nagging-$template_file-header.txt.tmpl", $vars, \$header) + || ThrowTemplateError($template->error()); + $header .= "\n"; + $template->process("email/request_nagging-$template_file.txt.tmpl", $vars, \$text) + || ThrowTemplateError($template->error()); + + my @parts = ( + Email::MIME->create( + attributes => { content_type => "text/plain" }, + body => $text, + ) + ); + if ($recipient->setting('email_format') eq 'html') { + my $html; + $template->process("email/request_nagging-$template_file.html.tmpl", $vars, \$html) + || ThrowTemplateError($template->error()); + push @parts, Email::MIME->create( + attributes => { content_type => "text/html" }, + body => $html, + ); } - # add this request to the current user's list - push(@$requests, $request); - } - send_email(%args, recipient => $current_recipient, requests => $requests); -} + my $email = Email::MIME->new($header); + $email->header_set('X-Generated-By' => hostname()); + if (scalar(@parts) == 1) { + $email->content_type_set($parts[0]->content_type); + } + else { + $email->content_type_set('multipart/alternative'); + } + $email->parts_set(\@parts); + if ($encrypt) { + $email->header_set('X-Bugzilla-Encrypt' => '1'); + } -sub send_email { - my (%vars) = @_; - my $vars = \%vars; - return unless $vars->{recipient} && @{ $vars->{requests} }; - - my $request_list = delete $vars->{requests}; - - # if securemail is installed, we need to encrypt or censor emails which - # contain non-public bugs - my $default_user = Bugzilla::User->new(); - my $securemail = $vars->{recipient}->can('public_key'); - my $has_key = $securemail && $vars->{recipient}->public_key; - # have to do this each time as objects are shared between requests - my $has_private_bug = 0; - foreach my $request (@{ $request_list }) { - # rebless bug objects into our subclass - bless($request->{bug}, 'Bugzilla::Extension::RequestNagger::Bug'); - # and tell that object to hide the summary if required - if ($securemail && !$default_user->can_see_bug($request->{bug})) { - $has_private_bug = 1; - $request->{bug}->{secure_bug} = !$has_key; + # send + if ($DO_NOT_NAG) { + # uncomment the following line to enable other extensions to + # process this email, including encryption + # Bugzilla::Hook::process('mailer_before_send', { email => $email }); + print $email->as_string, "\n"; } else { - $request->{bug}->{secure_bug} = 0; + MessageToMTA($email); } + + # nuke objects to avoid excessive memory usage + $requests->{$recipient_id} = undef; + Bugzilla->clear_request_cache(); } - my $encrypt = $securemail && $has_private_bug && $has_key; - - # restructure the list to group by requestee then flag type - my $requests = {}; - my %seen_types; - foreach my $request (@{ $request_list }) { - # by requestee - my $requestee_login = $request->{requestee}->login; - $requests->{$requestee_login} ||= { - requestee => $request->{requestee}, - types => {}, - typelist => [], - }; +} - # by flag type - my $types = $requests->{$requestee_login}->{types}; - my $flag_type = $request->{flag_type}; - $types->{$flag_type} ||= []; +sub _include_request { + my ($request, $report) = @_; - push @{ $types->{$flag_type} }, $request; - $seen_types{$requestee_login}{$flag_type} = 1; - } - foreach my $requestee_login (keys %seen_types) { - my @flag_types; - foreach my $flag_type (map { $_->{type} } FLAG_TYPES) { - push @flag_types, $flag_type if $seen_types{$requestee_login}{$flag_type}; + my $recipient = Bugzilla::User->new({ id => $request->{recipient_id}, cache => 1 }); + + if ($report eq 'requestee') { + # check recipient group membership + my $group; + foreach my $type (FLAG_TYPES) { + next unless $type->{type} eq $request->{flag_type}; + $group = $type->{group}; + last; } - $requests->{$requestee_login}->{typelist} = \@flag_types; + return 0 unless $recipient->in_group($group); } - $vars->{requests} = $requests; - - # generate email - my $template = Bugzilla->template_inner($vars->{recipient}->setting('lang')); - my $template_file = $vars->{template}; - - my ($header, $text); - $template->process("email/request_nagging-$template_file-header.txt.tmpl", $vars, \$header) - || ThrowTemplateError($template->error()); - $header .= "\n"; - $template->process("email/request_nagging-$template_file.txt.tmpl", $vars, \$text) - || ThrowTemplateError($template->error()); - - my @parts = ( - Email::MIME->create( - attributes => { content_type => "text/plain" }, - body => $text, - ) - ); - if ($vars->{recipient}->setting('email_format') eq 'html') { - my $html; - $template->process("email/request_nagging-$template_file.html.tmpl", $vars, \$html) - || ThrowTemplateError($template->error()); - push @parts, Email::MIME->create( - attributes => { content_type => "text/html" }, - body => $html, - ); + + # check bug visibility + return 0 unless $recipient->can_see_bug($request->{bug_id}); + + # check attachment visibility + if ($request->{attach_id}) { + my $attachment = Bugzilla::Attachment->new({ id => $request->{attach_id}, cache => 1 }); + return 0 if $attachment->isprivate && !$recipient->is_insider; } - my $email = Email::MIME->new($header); - $email->header_set('X-Generated-By' => hostname()); - if (scalar(@parts) == 1) { - $email->content_type_set($parts[0]->content_type); - } else { - $email->content_type_set('multipart/alternative'); + return 1; +} + +sub _create_objects { + my ($request) = @_; + + $request->{recipient} = Bugzilla::User->new({ id => $request->{recipient_id}, cache => 1 }); + $request->{setter} = Bugzilla::User->new({ id => $request->{setter_id}, cache => 1 }); + + if (defined $request->{requestee_id}) { + $request->{requestee} = Bugzilla::User->new({ id => $request->{requestee_id}, cache => 1 }); } - $email->parts_set(\@parts); - if ($encrypt) { - $email->header_set('X-Bugzilla-Encrypt' => '1'); + if (exists $request->{watcher_id}) { + $request->{watcher} = Bugzilla::User->new({ id => $request->{watcher_id}, cache => 1 }); } - # send - if ($DO_NOT_NAG) { - print $email->as_string, "\n"; - } else { - MessageToMTA($email); + $request->{bug} = Bugzilla::Extension::RequestNagger::Bug->new({ id => $request->{bug_id}, cache => 1 }); + $request->{flag} = Bugzilla::Flag->new({ id => $request->{flag_id}, cache => 1 }); + if (defined $request->{attach_id}) { + $request->{attachment} = Bugzilla::Attachment->new({ id => $request->{attach_id}, cache => 1 }); } } - diff --git a/extensions/RequestNagger/lib/Bug.pm b/extensions/RequestNagger/lib/Bug.pm index de6d5eae5..bd5bb7fd7 100644 --- a/extensions/RequestNagger/lib/Bug.pm +++ b/extensions/RequestNagger/lib/Bug.pm @@ -9,10 +9,22 @@ package Bugzilla::Extension::RequestNagger::Bug; use strict; use parent qw(Bugzilla::Bug); +use feature 'state'; + +use Bugzilla::User; sub short_desc { my ($self) = @_; - return $self->{secure_bug} ? '(Secure bug)' : $self->SUPER::short_desc; + return $self->{sanitise_bug} ? '(Secure bug)' : $self->SUPER::short_desc; +} + +sub is_private { + my ($self) = @_; + if (!exists $self->{is_private}) { + state $default_user //= Bugzilla::User->new(); + $self->{is_private} = !$default_user->can_see_bug($self); + } + return $self->{is_private}; } sub tooltip { @@ -21,7 +33,7 @@ sub tooltip { if ($self->bug_status eq 'RESOLVED') { $tooltip .= '/' . $self->resolution; } - if (!$self->{secure_bug}) { + if (!$self->{sanitise_bug}) { $tooltip .= ' ' . $self->product . ' :: ' . $self->component; } return $tooltip; diff --git a/extensions/RequestNagger/lib/Constants.pm b/extensions/RequestNagger/lib/Constants.pm index f61e616a7..899336a72 100644 --- a/extensions/RequestNagger/lib/Constants.pm +++ b/extensions/RequestNagger/lib/Constants.pm @@ -13,7 +13,9 @@ use base qw(Exporter); our @EXPORT = qw( FLAG_TYPES REQUESTEE_NAG_SQL - WATCHING_NAG_SQL + SETTER_NAG_SQL + WATCHING_REQUESTEE_NAG_SQL + WATCHING_SETTER_NAG_SQL ); # the order of this array determines the order used in email @@ -47,12 +49,14 @@ sub REQUESTEE_NAG_SQL { flags.bug_id, flags.attach_id, flags.modification_date, - requester.userid AS requester_id, - requestee.userid AS requestee_id + setter.userid AS setter_id, + requestee.userid AS requestee_id, + flags.requestee_id AS recipient_id, + flags.requestee_id AS target_id FROM flags INNER JOIN flagtypes ON flagtypes.id = flags.type_id - INNER JOIN profiles AS requester ON requester.userid = flags.setter_id + INNER JOIN profiles AS setter ON setter.userid = flags.setter_id INNER JOIN profiles AS requestee ON requestee.userid = flags.requestee_id INNER JOIN bugs ON bugs.bug_id = flags.bug_id INNER JOIN products ON products.id = bugs.product_id @@ -75,7 +79,48 @@ sub REQUESTEE_NAG_SQL { "; } -sub WATCHING_NAG_SQL { +sub SETTER_NAG_SQL { + my $dbh = Bugzilla->dbh; + my @flag_types_sql = map { $dbh->quote($_->{type}) } FLAG_TYPES; + + return " + SELECT + flagtypes.name AS flag_type, + flags.id AS flag_id, + flags.bug_id, + flags.attach_id, + flags.modification_date, + setter.userid AS setter_id, + requestee.userid AS requestee_id, + flags.setter_id AS recipient_id, + flags.setter_id AS target_id + FROM + flags + INNER JOIN flagtypes ON flagtypes.id = flags.type_id + INNER JOIN profiles AS setter ON setter.userid = flags.setter_id + LEFT JOIN profiles AS requestee ON requestee.userid = flags.requestee_id + INNER JOIN bugs ON bugs.bug_id = flags.bug_id + INNER JOIN products ON products.id = bugs.product_id + LEFT JOIN attachments ON attachments.attach_id = flags.attach_id + LEFT JOIN profile_setting ON profile_setting.setting_name = 'request_nagging' + AND profile_setting.user_id = flags.setter_id + LEFT JOIN nag_defer ON nag_defer.flag_id = flags.id + WHERE + " . $dbh->sql_in('flagtypes.name', \@flag_types_sql) . " + AND flags.status = '?' + AND products.nag_interval != 0 + AND TIMESTAMPDIFF(HOUR, flags.modification_date, CURRENT_DATE()) >= products.nag_interval + AND (profile_setting.setting_value IS NULL OR profile_setting.setting_value = 'on') + AND setter.disable_mail = 0 + AND nag_defer.id IS NULL + ORDER BY + flags.setter_id, + flagtypes.name, + flags.modification_date + "; +} + +sub WATCHING_REQUESTEE_NAG_SQL { my $dbh = Bugzilla->dbh; my @flag_types_sql = map { $dbh->quote($_->{type}) } FLAG_TYPES; @@ -87,12 +132,14 @@ sub WATCHING_NAG_SQL { flags.bug_id, flags.attach_id, flags.modification_date, - requester.userid AS requester_id, - requestee.userid AS requestee_id + setter.userid AS setter_id, + requestee.userid AS requestee_id, + nag_watch.watcher_id AS recipient_id, + requestee.userid AS target_id FROM flags INNER JOIN flagtypes ON flagtypes.id = flags.type_id - INNER JOIN profiles AS requester ON requester.userid = flags.setter_id + INNER JOIN profiles AS setter ON setter.userid = flags.setter_id INNER JOIN profiles AS requestee ON requestee.userid = flags.requestee_id INNER JOIN bugs ON bugs.bug_id = flags.bug_id INNER JOIN products ON products.id = bugs.product_id @@ -113,4 +160,45 @@ sub WATCHING_NAG_SQL { "; } +sub WATCHING_SETTER_NAG_SQL { + my $dbh = Bugzilla->dbh; + my @flag_types_sql = map { $dbh->quote($_->{type}) } FLAG_TYPES; + + return " + SELECT + nag_watch.watcher_id, + flagtypes.name AS flag_type, + flags.id AS flag_id, + flags.bug_id, + flags.attach_id, + flags.modification_date, + setter.userid AS setter_id, + requestee.userid AS requestee_id, + nag_watch.watcher_id AS recipient_id, + setter.userid AS target_id + FROM + flags + INNER JOIN flagtypes ON flagtypes.id = flags.type_id + INNER JOIN profiles AS setter ON setter.userid = flags.setter_id + LEFT JOIN profiles AS requestee ON requestee.userid = flags.requestee_id + INNER JOIN bugs ON bugs.bug_id = flags.bug_id + INNER JOIN products ON products.id = bugs.product_id + LEFT JOIN attachments ON attachments.attach_id = flags.attach_id + LEFT JOIN nag_defer ON nag_defer.flag_id = flags.id + INNER JOIN nag_watch ON nag_watch.nagged_id = flags.setter_id + INNER JOIN profiles AS watcher ON watcher.userid = nag_watch.watcher_id + WHERE + " . $dbh->sql_in('flagtypes.name', \@flag_types_sql) . " + AND flags.status = '?' + AND products.nag_interval != 0 + AND TIMESTAMPDIFF(HOUR, flags.modification_date, CURRENT_DATE()) >= products.nag_interval + AND watcher.disable_mail = 0 + ORDER BY + nag_watch.watcher_id, + flags.requestee_id, + flags.modification_date + "; +} + + 1; diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.html.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.html.tmpl deleted file mode 100644 index bdaaabb97..000000000 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.html.tmpl +++ /dev/null @@ -1,90 +0,0 @@ -[%# This Source Code Form is subject to the terms of the Mozilla Public - # License, v. 2.0. If a copy of the MPL was not distributed with this - # file, You can obtain one at http://mozilla.org/MPL/2.0/. - # - # This Source Code Form is "Incompatible With Secondary Licenses", as - # defined by the Mozilla Public License, v. 2.0. - #%] - -[% PROCESS "global/field-descs.none.tmpl" %] - -<!doctype html> -<html> - -<head> - <title>[[% terms.Bugzilla %]] Your Overdue Requests</title> -</head> - -<body bgcolor="#ffffff"> - -<p> - The following is a list of requests people have made of you, which are - currently overdue. To avoid disappointing others, please deal with them as - quickly as possible. -</p> - -[% requests = requests.item(recipient.login) %] -[% FOREACH type = requests.typelist %] - - <h3> - [% type FILTER upper FILTER html %] requests - <span style="font-size: x-small; font-weight: normal"> - (<a href="[% urlbase FILTER none %]buglist.cgi?bug_id= - [% FOREACH request = requests.types.$type %] - [% request.bug.id FILTER none %] - [% "%2C" UNLESS loop.last %] - [% END %]">buglist</a>) - </span> - </h3> - - <ul> - [% FOREACH request = requests.types.$type %] - <li> - <a href="[% urlbase FILTER none %]show_bug.cgi?id=[% request.bug.id FILTER none %]" - title="[% request.bug.tooltip FILTER html %]"> - [% request.bug.id FILTER none %] - [% request.bug.short_desc FILTER html %] - </a><br> - <b>[%+ request.flag.age FILTER html %]</b> from [% request.requester.identity FILTER html %]<br> - <div style="font-size: x-small"> - [% IF request.attachment %] - <a href="[% urlbase FILTER none %]attachment.cgi?id=[% request.attachment.id FILTER none %]&action=edit">Details</a> - [% IF request.attachment.ispatch %] - | <a href="[% urlbase FILTER none %]attachment.cgi?id=[% request.attachment.id FILTER none %]&action=diff">Diff</a> - | <a href="[% urlbase FILTER none %]review?bug=[% request.bug.id FILTER none %]&attachment=[% request.attachment.id FILTER none %]">Review</a> - [% END %] - | - [% END %] - <a href="[% urlbase FILTER none %]request_defer?flag=[% request.flag.id FILTER none %]">Defer</a> - </div> - <br> - </li> - [% END %] - </ul> - -[% END %] - -<div> - <hr style="border: 1px dashed #969696"> - [% IF requests.types.item('review').size || requests.types.item('feedback').size %] - <a href="https://wiki.mozilla.org/BMO/Handling_Requests"> - Guidance on handling requests - </a><br> - [% END %] - <a href="[% urlbase FILTER none %]request.cgi?action=queue&requestee=[% recipient.login FILTER uri %]&group=type"> - See all your overdue requests - </a><br> - <a href="[% urlbase FILTER none %]userprefs.cgi#request_nagging"> - Opt out of these emails - </a><br> -</div> - -<div style="font-size: 90%; color: #666666"> - <hr style="border: 1px dashed #969696"> - <b>You are receiving this mail because:</b> - <ul> - <li>You have overdue requests.</li> - </ul> -</div> -@@body-headers@@ -</body> -</html> diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee-header.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-user-header.txt.tmpl index 8ad9d6cb1..6bb9e997b 100644 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee-header.txt.tmpl +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-user-header.txt.tmpl @@ -6,14 +6,20 @@ # defined by the Mozilla Public License, v. 2.0. #%] -[% PROCESS "global/field-descs.none.tmpl" %] -[% PROCESS "global/reason-descs.none.tmpl" %] +[% + PROCESS "global/field-descs.none.tmpl"; + PROCESS "global/reason-descs.none.tmpl"; + summary = requests.item(recipient.login).summary; +%] + From: [% Param('mailfrom') %] To: [% recipient.email %] -Subject: [[% terms.Bugzilla %]] Your Overdue Requests - ([% FOREACH type = requests.item(recipient.email).typelist %] - [%- requests.item(recipient.email).types.item(type).size %] [%+ type %] - [% ", " UNLESS loop.last %] - [% END %]) +Subject: [[% terms.Bugzilla %]] Overdue Requests + [% IF summary.requestee %] + (Of you: [% summary.requestee %]) + [% END %] + [% IF summary.setter %] + (By you: [% summary.setter %]) + [% END %] Date: [% date %] X-Bugzilla-Type: nag diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-user.html.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-user.html.tmpl new file mode 100644 index 000000000..9aeb73f61 --- /dev/null +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-user.html.tmpl @@ -0,0 +1,115 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% + PROCESS "global/field-descs.none.tmpl"; + requestee = requests.item(recipient.login).requestee; + setter = requests.item(recipient.login).setter; + summary = requests.item(recipient.login).summary; + types = requests.item(recipient.login).types; +%] + +<!doctype html> +<html> + +<head> + <title>[[% terms.Bugzilla %]] Your Overdue Requests</title> +</head> + +<body bgcolor="#ffffff"> + +[% IF requestee.size %] + <h3>Overdue requests requiring action from you:</h3> + <div>[% summary.requestee FILTER html %]</div> + [% PROCESS requests report="requestee" requests=requestee %] +[% END %] + +[% IF requestee.size && setter.size %] + <hr> +[% END %] + +[% IF setter.size %] + <h3>Overdue requests you have requested:</h3> + <div>[% summary.setter FILTER html %]</div> + [% PROCESS requests report="setter" requests=setter %] +[% END %] + +[% BLOCK requests %] + [% FOREACH type IN types.item(report) %] + <h3> + [% type FILTER upper FILTER html %] requests + <span style="font-size: x-small; font-weight: normal"> + (<a href="[% urlbase FILTER none %]buglist.cgi?bug_id= + [% FOREACH request IN requests.item(type) %] + [% request.bug.id FILTER none %] + [% "%2C" UNLESS loop.last %] + [% END %]">buglist</a>) + </span> + </h3> + + <ul> + [% FOREACH request IN requests.item(type) %] + <li> + <a href="[% urlbase FILTER none %]show_bug.cgi?id=[% request.bug.id FILTER none %]" + title="[% request.bug.tooltip FILTER html %]"> + [% request.bug.id FILTER none %] - [% request.bug.short_desc FILTER html %] + </a><br> + <b>[%+ request.flag.age FILTER html %]</b> + [% IF report == "requestee" %] + from [% request.setter.realname || request.setter.login FILTER html %] + [% ELSIF request.requestee %] + to [% request.requestee.realname || request.setter.login FILTER html %] + [% ELSE %] + to <i>anyone</i> + [% END %] + <br> + [% IF report == "requestee" %] + <div style="font-size: x-small"> + [% IF request.attachment %] + <a href="[% urlbase FILTER none %]attachment.cgi?id=[% request.attachment.id FILTER none %]&action=edit">Details</a> + [% IF request.attachment.ispatch %] + | <a href="[% urlbase FILTER none %]attachment.cgi?id=[% request.attachment.id FILTER none %]&action=diff">Diff</a> + | <a href="[% urlbase FILTER none %]review?bug=[% request.bug.id FILTER none %]&attachment=[% request.attachment.id FILTER none %]">Review</a> + [% END %] + | + [% END %] + <a href="[% urlbase FILTER none %]request_defer?flag=[% request.flag.id FILTER none %]">Defer</a> + </div> + [% END %] + <br> + </li> + [% END %] + </ul> + [% END %] +[% END %] + +<div> + <hr style="border: 1px dashed #969696"> + [% IF requestee.item('review').size || requestee.item('feedback').size %] + <a href="https://wiki.mozilla.org/BMO/Handling_Requests"> + Guidance on handling requests + </a><br> + [% END %] + <a href="[% urlbase FILTER none %]request.cgi?action=queue&requestee=[% recipient.login FILTER uri %]&group=type"> + See all your overdue requests + </a><br> + <a href="[% urlbase FILTER none %]userprefs.cgi#request_nagging"> + Opt out of these emails + </a><br> +</div> + +<div style="font-size: 90%; color: #666666"> + <hr style="border: 1px dashed #969696"> + <b>You are receiving this mail because:</b> + <ul> + <li>You have overdue requests.</li> + </ul> +</div> +@@body-headers@@ +</body> +</html> diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-user.txt.tmpl index 4e3f67090..5138f5f00 100644 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.txt.tmpl +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-user.txt.tmpl @@ -6,31 +6,58 @@ # defined by the Mozilla Public License, v. 2.0. #%] -[% PROCESS "global/field-descs.none.tmpl" %] +[% + PROCESS "global/field-descs.none.tmpl"; + requestee = requests.item(recipient.login).requestee; + setter = requests.item(recipient.login).setter; + summary = requests.item(recipient.login).summary; + types = requests.item(recipient.login).types; +%] -The following is a list of requests people have made of you, which are -currently overdue. To avoid disappointing others, please deal with them as -quickly as possible. +[% IF requestee.size %] +Overdue requests requiring action from you: +[%+ summary.requestee %] -[% requests = requests.item(recipient.login) %] -[% FOREACH type = requests.typelist %] +[%+ PROCESS requests report="requestee" request_list=requestee %] +[% END %] + +[% IF requestee.size && setter.size %] +- +[% END %] + +[% IF setter.size %] +Overdue requests you have requested: +[%+ summary.setter %] + +[%+ PROCESS requests report="setter" request_list=setter %] +[% END %] + +[% BLOCK requests %] +[% FOREACH type IN types.item(report) %] :: [% type FILTER upper FILTER html %] requests -[% FOREACH request = requests.types.$type %] +[% FOREACH request IN request_list.item(type) %] [[% terms.Bug %] [%+ request.bug.id %]] [% request.bug.short_desc %] - [%+ request.flag.age %] from [% request.requester.identity %] + [% IF report == "requestee" %] + [%+ request.flag.age %] from [% request.setter.realname || request.setter.login %] + [% ELSE %] + [%+ request.flag.age %] to [% request.requestee.realname || request.requestee.login %] + [% END %] [%+ urlbase %]show_bug.cgi?id=[% request.bug.id +%] [% IF request.attachment && request.attachment.ispatch %] Review: [% urlbase %]review?bug=[% request.bug.id %]&attachment=[% request.attachment.id %] [% END %] + [% IF report == "requestee" %] Defer: [% urlbase %]request_defer?flag=[% request.flag.id %] + [% END %] [% END %] [% END %] +[% END %] :: -[% IF requests.types.item('review').size || requests.types.item('feedback').size %] +[% IF requestee.item('review').size || requestee.item('feedback').size %] Guidance on handling requests: https://wiki.mozilla.org/BMO/Handling_Requests [% END %] diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-watching-header.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-watching-header.txt.tmpl index 261e92f13..d825cb459 100644 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-watching-header.txt.tmpl +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-watching-header.txt.tmpl @@ -6,10 +6,12 @@ # defined by the Mozilla Public License, v. 2.0. #%] -[% PROCESS "global/field-descs.none.tmpl" %] -[% PROCESS "global/reason-descs.none.tmpl" %] +[% + PROCESS "global/field-descs.none.tmpl"; + PROCESS "global/reason-descs.none.tmpl"; +%] From: [% Param('mailfrom') %] To: [% recipient.email %] -Subject: [[% terms.Bugzilla %]] Overdue Requests Report +Subject: [[% terms.Bugzilla %]] Overdue Requests Date: [% date %] X-Bugzilla-Type: nag-watch diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-watching.html.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-watching.html.tmpl index 91fb36e1d..14e4d7f4e 100644 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-watching.html.tmpl +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-watching.html.tmpl @@ -18,70 +18,55 @@ <body bgcolor="#ffffff"> <p> - The following is a list of people who you are watching that have overdue - requests. + The following is a list of people who you are watching that are involved in + overdue requests. </p> -<hr> - [% FOREACH login = requests.keys.sort %] - [% requestee = requests.$login.requestee %] - [% requestee.identity FILTER html %] + [% + target = requests.item(login).target; + requestee = requests.item(login).requestee; + setter = requests.item(login).setter; + summary = requests.item(login).summary; + bug_ids = requests.item(login).bug_ids; + %] + <h3> + [% target.realname || target.login FILTER html %] + </h3> <ul> - <li> - [%+ FOREACH type = requests.$login.typelist %] - [% requests.$login.types.item(type).size %] [%+ type FILTER html %] - [% ", " UNLESS loop.last %] - [% END %] + [% IF requestee.size %] + <li> + Requested of: [% summary.requestee FILTER html %] + (<a href="[% urlbase FILTER none %]buglist.cgi?bug_id=[% bug_ids.requestee.join(",") FILTER uri %]">buglist</a>) + </li> + [% END %] + [% IF setter.size %] + <li> + Waiting on: [% summary.setter FILTER html %] + (<a href="[% urlbase FILTER none %]buglist.cgi?bug_id=[% bug_ids.setter.join(",") FILTER uri %]">buglist</a>) + </li> + [% END %] </li> </ul> [% END %] [% FOREACH login = requests.keys.sort %] - [% requestee = requests.$login.requestee %] - - [% bug_ids = [] %] - [% FOREACH type = requests.$login.typelist %] - [% FOREACH request = requests.$login.types.$type %] - [% bug_ids.push(request.bug.id) %] - [% END %] - [% END %] + [% + target = requests.item(login).target; + requestee = requests.item(login).requestee; + setter = requests.item(login).setter; + summary = requests.item(login).summary; + types = requests.item(login).types; + %] <hr> + <h3> - [% requestee.identity FILTER html %] - <span style="font-size: x-small; font-weight: normal"> - (<a href="[% urlbase FILTER none %]buglist.cgi?bug_id=[% bug_ids.join(",") FILTER uri %]">buglist</a>) - </span><br> - <span style="font-size: x-small; font-weight: normal"> - [% FOREACH type = requests.$login.typelist %] - [% requests.$login.types.item(type).size %] [%+ type FILTER html %] - [% ", " UNLESS loop.last %] - [% END %] - </span> + [% target.realname || target.login FILTER html %]<br> </h3> - [% FOREACH type = requests.$login.typelist %] - - <h3>[% type FILTER upper FILTER html %] requests</h3> - - <ul> - [% FOREACH request = requests.$login.types.$type %] - <li> - <a href="[% urlbase FILTER none %]show_bug.cgi?id=[% request.bug.id FILTER none %]" - title="[% request.bug.tooltip FILTER html %]"> - [% request.bug.id FILTER none %] - [% request.bug.short_desc FILTER html %] - </a><br> - <b>[%+ request.flag.age FILTER html %]</b> from [% request.requester.identity FILTER html %]<br> - [% IF request.flag.deferred %] - Deferred until [%+ request.flag.deferred.ymd FILTER html %]<br> - [% END %] - <br> - </li> - [% END %] - </ul> - - [% END %] + [% PROCESS requests report="requestee" request_list=requestee %] + [% PROCESS requests report="setter" request_list=setter %] [% END %] @@ -102,3 +87,39 @@ @@body-headers@@ </body> </html> + +[% BLOCK requests %] + [% RETURN UNLESS request_list.size %] + [% FOREACH type IN types.item(report) %] + + <h3> + [% type FILTER upper FILTER html %] + [%= report == "requestee" ? "requested of" : "waiting on" FILTER none %] + </h3> + + <ul> + [% FOREACH request IN request_list.item(type) %] + <li> + <a href="[% urlbase FILTER none %]show_bug.cgi?id=[% request.bug.id FILTER none %]" + title="[% request.bug.tooltip FILTER html %]"> + [% request.bug.id FILTER none %] - [% request.bug.short_desc FILTER html %] + </a><br> + + <b>[% request.flag.age FILTER html %]</b> + [% IF report == "requestee" %] + from [% request.setter.realname || request.setter.login FILTER html %] + [% ELSE %] + to [% request.requestee.realname || request.requestee.login FILTER html %] + [% END %] + + [% IF request.flag.deferred %] + <br> + Deferred until [%+ request.flag.deferred.ymd FILTER html %]<br> + [% END %] + </li> + [% END %] + </ul> + + [% END %] + +[% END %] diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-watching.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-watching.txt.tmpl index 8bc5a3b7c..0e80cc73c 100644 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-watching.txt.tmpl +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-watching.txt.tmpl @@ -8,32 +8,28 @@ [% PROCESS "global/field-descs.none.tmpl" %] -The following is a list of people who you are watching that have overdue -requests. +[% FOREACH login IN requests.keys.sort %] +[% + target = requests.item(login).target; + requestee = requests.item(login).requestee; + setter = requests.item(login).setter; + summary = requests.item(login).summary; + types = requests.item(login).types; +%] -[% FOREACH login = requests.keys.sort %] -[% requestee = requests.$login.requestee %] :: -:: [% requestee.identity %] -:: [% FOREACH type = requests.$login.typelist %] - [%- requests.$login.types.item(type).size %] [%+ type %] - [% ", " UNLESS loop.last %] - [% END %] +:: [% target.identity %] +[% IF requestee.size %] +:: Requested of: [% summary.requestee %] +[% END %] +[% IF setter.size %] +:: Waiting on: [% summary.setter %] +[% END %] :: -[% FOREACH type = requests.$login.typelist %] -:: [% type FILTER upper FILTER html %] requests +[%+ PROCESS requests report="requestee" request_list=requestee %] -[% FOREACH request = requests.$login.types.$type %] -[[% terms.Bug %] [%+ request.bug.id %]] [% request.bug.short_desc %] - [%+ request.flag.age %] from [% request.requester.identity %] - [%+ urlbase %]show_bug.cgi?id=[% request.bug.id +%] - [% IF request.flag.deferred %] - Deferred until [%+ request.flag.deferred.ymd %] - [% END %] - -[% END %] -[% END %] +[%+ PROCESS requests report="setter" request_list=setter %] [% END %] @@ -47,3 +43,26 @@ You are receiving this mail because: you are watching someone with overdue requests. @@body-headers@@ + +[% BLOCK requests %] +[% RETURN UNLESS request_list.size %] + +[% FOREACH type IN types.item(report) %] +:: [% type FILTER upper %] [%= report == "requestee" ? "requested of" : "waiting on" %] + +[% FOREACH request IN request_list.item(type) %] +[[% terms.Bug %] [%+ request.bug.id %]] [% request.bug.short_desc %] + [% IF report == "requestee" %] + [%+ request.flag.age %] from [% request.setter.realname || request.setter.login %] + [% ELSE %] + [%+ request.flag.age %] to [% request.requestee.realname || request.requestee.login %] + [% END %] + [%+ urlbase %]show_bug.cgi?id=[% request.bug.id +%] + [% IF request.flag.deferred %] + Deferred until [%+ request.flag.deferred.ymd %] + [% END %] + +[% END %] +[% END %] + +[% END %] |