From 70b298ecbd3aba8f24bf6d0147bece13b81d6040 Mon Sep 17 00:00:00 2001 From: Byron Jones Date: Tue, 19 May 2015 20:46:40 +0800 Subject: Bug 1163868: Include requests from others in RequestNagger --- extensions/RequestNagger/bin/send-request-nags.pl | 316 ++++++++++++--------- extensions/RequestNagger/lib/Bug.pm | 16 +- extensions/RequestNagger/lib/Constants.pm | 104 ++++++- .../request_nagging-requestee-header.txt.tmpl | 19 -- .../email/request_nagging-requestee.html.tmpl | 90 ------ .../email/request_nagging-requestee.txt.tmpl | 47 --- .../email/request_nagging-user-header.txt.tmpl | 25 ++ .../default/email/request_nagging-user.html.tmpl | 115 ++++++++ .../en/default/email/request_nagging-user.txt.tmpl | 74 +++++ .../email/request_nagging-watching-header.txt.tmpl | 8 +- .../email/request_nagging-watching.html.tmpl | 121 ++++---- .../email/request_nagging-watching.txt.tmpl | 61 ++-- 12 files changed, 620 insertions(+), 376 deletions(-) delete mode 100644 extensions/RequestNagger/template/en/default/email/request_nagging-requestee-header.txt.tmpl delete mode 100644 extensions/RequestNagger/template/en/default/email/request_nagging-requestee.html.tmpl delete mode 100644 extensions/RequestNagger/template/en/default/email/request_nagging-requestee.txt.tmpl create mode 100644 extensions/RequestNagger/template/en/default/email/request_nagging-user-header.txt.tmpl create mode 100644 extensions/RequestNagger/template/en/default/email/request_nagging-user.html.tmpl create mode 100644 extensions/RequestNagger/template/en/default/email/request_nagging-user.txt.tmpl 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-header.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-requestee-header.txt.tmpl deleted file mode 100644 index 8ad9d6cb1..000000000 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee-header.txt.tmpl +++ /dev/null @@ -1,19 +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" %] -[% PROCESS "global/reason-descs.none.tmpl" %] -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 %]) -Date: [% date %] -X-Bugzilla-Type: nag 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" %] - - - - - - [[% terms.Bugzilla %]] Your Overdue Requests - - - - -

- 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. -

- -[% requests = requests.item(recipient.login) %] -[% FOREACH type = requests.typelist %] - -

- [% type FILTER upper FILTER html %] requests - - (buglist) - -

- - - -[% END %] - -
-
- [% IF requests.types.item('review').size || requests.types.item('feedback').size %] - - Guidance on handling requests -
- [% END %] - - See all your overdue requests -
- - Opt out of these emails -
-
- -
-
- You are receiving this mail because: - -
-@@body-headers@@ - - diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.txt.tmpl deleted file mode 100644 index 4e3f67090..000000000 --- a/extensions/RequestNagger/template/en/default/email/request_nagging-requestee.txt.tmpl +++ /dev/null @@ -1,47 +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" %] - -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. - -[% requests = requests.item(recipient.login) %] -[% FOREACH type = requests.typelist %] -:: [% type FILTER upper FILTER html %] requests - -[% FOREACH request = requests.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.attachment && request.attachment.ispatch %] - Review: [% urlbase %]review?bug=[% request.bug.id %]&attachment=[% request.attachment.id %] - [% END %] - Defer: [% urlbase %]request_defer?flag=[% request.flag.id %] - -[% END %] -[% END %] - -:: - -[% IF requests.types.item('review').size || requests.types.item('feedback').size %] -Guidance on handling requests: - https://wiki.mozilla.org/BMO/Handling_Requests -[% END %] - -See all your overdue requests: - [%+ urlbase %]request.cgi?action=queue&requestee=[% recipient.login FILTER uri %]&group=type - -Opt out of these emails: - [%+ urlbase %]userprefs.cgi#request_nagging - --- -You are receiving this mail because: you have overdue requests. - -@@body-headers@@ diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-user-header.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-user-header.txt.tmpl new file mode 100644 index 000000000..6bb9e997b --- /dev/null +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-user-header.txt.tmpl @@ -0,0 +1,25 @@ +[%# 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"; + PROCESS "global/reason-descs.none.tmpl"; + summary = requests.item(recipient.login).summary; +%] + +From: [% Param('mailfrom') %] +To: [% recipient.email %] +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; +%] + + + + + + [[% terms.Bugzilla %]] Your Overdue Requests + + + + +[% IF requestee.size %] +

Overdue requests requiring action from you:

+
[% summary.requestee FILTER html %]
+ [% PROCESS requests report="requestee" requests=requestee %] +[% END %] + +[% IF requestee.size && setter.size %] +
+[% END %] + +[% IF setter.size %] +

Overdue requests you have requested:

+
[% summary.setter FILTER html %]
+ [% PROCESS requests report="setter" requests=setter %] +[% END %] + +[% BLOCK requests %] + [% FOREACH type IN types.item(report) %] +

+ [% type FILTER upper FILTER html %] requests + + (buglist) + +

+ + + [% END %] +[% END %] + +
+
+ [% IF requestee.item('review').size || requestee.item('feedback').size %] + + Guidance on handling requests +
+ [% END %] + + See all your overdue requests +
+ + Opt out of these emails +
+
+ +
+
+ You are receiving this mail because: + +
+@@body-headers@@ + + diff --git a/extensions/RequestNagger/template/en/default/email/request_nagging-user.txt.tmpl b/extensions/RequestNagger/template/en/default/email/request_nagging-user.txt.tmpl new file mode 100644 index 000000000..5138f5f00 --- /dev/null +++ b/extensions/RequestNagger/template/en/default/email/request_nagging-user.txt.tmpl @@ -0,0 +1,74 @@ +[%# 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; +%] + +[% IF requestee.size %] +Overdue requests requiring action from you: +[%+ summary.requestee %] + +[%+ 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 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.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 requestee.item('review').size || requestee.item('feedback').size %] +Guidance on handling requests: + https://wiki.mozilla.org/BMO/Handling_Requests +[% END %] + +See all your overdue requests: + [%+ urlbase %]request.cgi?action=queue&requestee=[% recipient.login FILTER uri %]&group=type + +Opt out of these emails: + [%+ urlbase %]userprefs.cgi#request_nagging + +-- +You are receiving this mail because: you have overdue requests. + +@@body-headers@@ 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 @@

- 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.

-
- [% 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; + %] +

+ [% target.realname || target.login FILTER html %] +

[% 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; + %]
+

- [% requestee.identity FILTER html %] - - (buglist) -
- - [% FOREACH type = requests.$login.typelist %] - [% requests.$login.types.item(type).size %] [%+ type FILTER html %] - [% ", " UNLESS loop.last %] - [% END %] - + [% target.realname || target.login FILTER html %]

- [% FOREACH type = requests.$login.typelist %] - -

[% type FILTER upper FILTER html %] requests

- - - - [% END %] + [% PROCESS requests report="requestee" request_list=requestee %] + [% PROCESS requests report="setter" request_list=setter %] [% END %] @@ -102,3 +87,39 @@ @@body-headers@@ + +[% BLOCK requests %] + [% RETURN UNLESS request_list.size %] + [% FOREACH type IN types.item(report) %] + +

+ [% type FILTER upper FILTER html %] + [%= report == "requestee" ? "requested of" : "waiting on" FILTER none %] +

+ + + + [% 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 %] -- cgit v1.2.3-24-g4f1b