has 'products' => (is => 'lazy', isa => ArrayRef [Str],);
+has 'missing_products' => (is => 'lazy', isa => ArrayRef [Str],);
+
+has 'missing_components' => (is => 'lazy', isa => ArrayRef [Str],);
+
has 'initial_bug_ids' => (is => 'lazy', isa => ArrayRef [Int],);
has 'initial_bugs' => (
return \@products;
}
+sub _build_missing_products {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ my @products = map { $dbh->quote($_) } @{$self->products};
+ my $query = qq{
+ SELECT
+ name
+ FROM
+ products
+ WHERE
+ @{[$dbh->sql_in('products.name', \@products)]}
+ };
+ my $found_products = Bugzilla->dbh->selectcol_arrayref($query);
+ return (diff_arrays($self->products, $found_products))[0];
+}
+
+sub _build_missing_components {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $products = join ', ', map { $dbh->quote($_) } @{$self->products};
+ my @named_components = ();
+ my @missing_components = ();
+ foreach my $team (values %{$self->teams}) {
+ foreach my $product (keys %$team) {
+ if (exists $team->{$product}->{named_components}) {
+ foreach my $component (@{$team->{$product}->{named_components}}) {
+ push @named_components, [$product, $component];
+ }
+ }
+ }
+ }
+
+ my @components = map { $dbh->quote($_->[1]) } @named_components;
+ my $query = qq{
+ SELECT
+ product.name,
+ component.name
+ FROM
+ components AS component
+ JOIN products AS product ON component.product_id = product.id
+ WHERE
+ @{[$dbh->sql_in('component.name', \@components)]}
+ };
+ my $found_components = Bugzilla->dbh->selectall_arrayref($query);
+
+ foreach my $named_component (@named_components) {
+ my $found = 0;
+ foreach my $found_component (@$found_components) {
+ if (lc $named_component->[0] eq lc $found_component->[0] && lc $named_component->[1] eq lc $found_component->[1])
+ {
+ $found = 1;
+ last;
+ }
+ }
+ push @missing_components, "$named_component->[0]::$named_component->[1]" if !$found;
+ }
+ return \@missing_components;
+}
+
sub _build_initial_bug_ids {
# TODO: Handle changes in product (e.g. gravyarding) by searching the events table
);
my $bugs_by_team = $report->results->[-1]->{bugs_by_team};
-my @sorted_team_names = sort { ## no critic qw(BuiltinFunctions::ProhibitReverseSortBlock
- @{$bugs_by_team->{$b}->{open}} <=> @{$bugs_by_team->{$a}->{open}} ## no critic qw(Freenode::DollarAB)
+my @sorted_team_names = sort { ## no critic qw(BuiltinFunctions::ProhibitReverseSortBlock
+ @{$bugs_by_team->{$b}->{open}} <=> @{$bugs_by_team->{$a}->{open}} ## no critic qw(Freenode::DollarAB)
|| $a cmp $b
} keys %$teams;
my $vars = {
- urlbase => Bugzilla->localconfig->{urlbase},
- report_week => $report_week,
- teams => \@sorted_team_names,
- sec_keywords => $sec_keywords,
- results => $report->results,
- deltas => $report->deltas,
- build_bugs_link => \&build_bugs_link,
+ urlbase => Bugzilla->localconfig->{urlbase},
+ report_week => $report_week,
+ teams => \@sorted_team_names,
+ sec_keywords => $sec_keywords,
+ results => $report->results,
+ deltas => $report->deltas,
+ missing_products => $report->missing_products,
+ missing_components => $report->missing_components,
+ build_bugs_link => \&build_bugs_link,
};
$template->process('reports/email/security-risk.html.tmpl', $vars, \$html) or ThrowTemplateError($template->error());
Open<br>[% results.reverse.0.date FILTER time('%m/%d') %]
</th>
<th style="padding: 0px 15px 10px 0px; text-align: right;">Closed<br />Last Week</th>
- <th style="padding: 0px 15px 10px 0px; text-align: right;">Added<br />Last Week</th>
+ <th style="padding: 0px 15px 10px 0px; text-align: right; border-right: 1px solid grey;">Added<br />Last Week</th>
[% FOREACH result IN results.reverse %]
[% NEXT IF loop.count < 2 %]
[% LAST IF loop.count > 4 %]
[% NEXT IF loop.count < 2 %]
[% LAST IF loop.count > 4 %]
<td style="padding: 0px 15px 10px [% IF loop.count == 2 %] 10px [% ELSE %] 0px [% END %]; text-align: right; [% IF loop.count == 1 %] border-right: 1px solid grey; [% END %]">
- [% IF result.bugs_by_sec_keyword.$keyword.open %]
+ [% IF result.bugs_by_sec_keyword.$keyword.open.size %]
<a style="text-decoration: none;" href="[% build_bugs_link(result.bugs_by_sec_keyword.$keyword.open) FILTER html %]">
[% result.bugs_by_sec_keyword.$keyword.open.size FILTER html %]
</a>
<p>Attached to this email are some graphs with stats for the past 12 months.</p>
+[% IF missing_products.size %]
+ <p>The following products requested on this report are no longer active in BMO:
+ [% FOREACH missing_product IN missing_products %]
+ [% missing_product FILTER html %][% ", " FILTER html IF not loop.last %]
+ [% END %]
+ <p>
+[% END %]
+
+[% IF missing_components.size %]
+ <p>The following components requested on this report are no longer active in BMO:
+ [% FOREACH missing_component IN missing_components %]
+ [% missing_component FILTER html %][% ", " FILTER html IF not loop.last %]
+ [% END %]
+ </p>
+[% END %]
+
+[% IF missing_products.size || missing_components.size %]
+ <p>Please file a [% terms.bug %] in bugzilla.mozilla.org::Administration to update the team list.</p>
+[% END %]
+
</body>
</html>