summaryrefslogtreecommitdiffstats
path: root/extensions/BMO/lib/Reports/Triage.pm
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/BMO/lib/Reports/Triage.pm')
-rw-r--r--extensions/BMO/lib/Reports/Triage.pm516
1 files changed, 268 insertions, 248 deletions
diff --git a/extensions/BMO/lib/Reports/Triage.pm b/extensions/BMO/lib/Reports/Triage.pm
index 55eeb17eb..0ccbbee6e 100644
--- a/extensions/BMO/lib/Reports/Triage.pm
+++ b/extensions/BMO/lib/Reports/Triage.pm
@@ -25,261 +25,279 @@ use List::MoreUtils qw(any);
# set an upper limit on the *unfiltered* number of bugs to process
use constant MAX_NUMBER_BUGS => 4000;
-use constant DEFAULT_OWNER_PRODUCTS => (
- 'Core',
- 'Firefox',
- 'Firefox for Android',
- 'Firefox for iOS',
- 'Toolkit',
-);
+use constant DEFAULT_OWNER_PRODUCTS =>
+ ('Core', 'Firefox', 'Firefox for Android', 'Firefox for iOS', 'Toolkit',);
sub unconfirmed {
- my ($vars, $filter) = @_;
- my $dbh = Bugzilla->dbh;
- my $input = Bugzilla->input_params;
- my $user = Bugzilla->user;
-
- if (exists $input->{'action'} && $input->{'action'} eq 'run' && $input->{'product'}) {
-
- # load product and components from input
-
- my $product = Bugzilla::Product->new({ name => $input->{'product'} })
- || ThrowUserError('invalid_object', { object => 'Product', value => $input->{'product'} });
-
- my @component_ids;
- if ($input->{'component'} ne '') {
- my $ra_components = ref($input->{'component'})
- ? $input->{'component'} : [ $input->{'component'} ];
- foreach my $component_name (@$ra_components) {
- my $component = Bugzilla::Component->new({ name => $component_name, product => $product })
- || ThrowUserError('invalid_object', { object => 'Component', value => $component_name });
- push @component_ids, $component->id;
- }
- }
+ my ($vars, $filter) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
- # determine which comment filters to run
+ if ( exists $input->{'action'}
+ && $input->{'action'} eq 'run'
+ && $input->{'product'})
+ {
- my $filter_commenter = $input->{'filter_commenter'};
- my $filter_commenter_on = $input->{'commenter'};
- my $filter_last = $input->{'filter_last'};
- my $filter_last_period = $input->{'last'};
+ # load product and components from input
- if (!$filter_commenter || $filter_last) {
- $filter_commenter = '1';
- $filter_commenter_on = 'reporter';
- }
+ my $product
+ = Bugzilla::Product->new({name => $input->{'product'}})
+ || ThrowUserError('invalid_object',
+ {object => 'Product', value => $input->{'product'}});
- my $filter_commenter_id;
- if ($filter_commenter && $filter_commenter_on eq 'is') {
- Bugzilla::User::match_field({ 'commenter_is' => {'type' => 'single'} });
- my $user = Bugzilla::User->new({ name => $input->{'commenter_is'} })
- || ThrowUserError('invalid_object', { object => 'User', value => $input->{'commenter_is'} });
- $filter_commenter_id = $user ? $user->id : 0;
- }
+ my @component_ids;
+ if ($input->{'component'} ne '') {
+ my $ra_components
+ = ref($input->{'component'})
+ ? $input->{'component'}
+ : [$input->{'component'}];
+ foreach my $component_name (@$ra_components) {
+ my $component
+ = Bugzilla::Component->new({name => $component_name, product => $product})
+ || ThrowUserError('invalid_object',
+ {object => 'Component', value => $component_name});
+ push @component_ids, $component->id;
+ }
+ }
- my $filter_last_time;
- if ($filter_last) {
- if ($filter_last_period eq 'is') {
- $filter_last_period = -1;
- $filter_last_time = str2time($input->{'last_is'} . " 00:00:00") || 0;
- } else {
- detaint_natural($filter_last_period);
- $filter_last_period = 14 if $filter_last_period < 14;
- }
- }
+ # determine which comment filters to run
+
+ my $filter_commenter = $input->{'filter_commenter'};
+ my $filter_commenter_on = $input->{'commenter'};
+ my $filter_last = $input->{'filter_last'};
+ my $filter_last_period = $input->{'last'};
+
+ if (!$filter_commenter || $filter_last) {
+ $filter_commenter = '1';
+ $filter_commenter_on = 'reporter';
+ }
+
+ my $filter_commenter_id;
+ if ($filter_commenter && $filter_commenter_on eq 'is') {
+ Bugzilla::User::match_field({'commenter_is' => {'type' => 'single'}});
+ my $user
+ = Bugzilla::User->new({name => $input->{'commenter_is'}})
+ || ThrowUserError('invalid_object',
+ {object => 'User', value => $input->{'commenter_is'}});
+ $filter_commenter_id = $user ? $user->id : 0;
+ }
- # form sql queries
+ my $filter_last_time;
+ if ($filter_last) {
+ if ($filter_last_period eq 'is') {
+ $filter_last_period = -1;
+ $filter_last_time = str2time($input->{'last_is'} . " 00:00:00") || 0;
+ }
+ else {
+ detaint_natural($filter_last_period);
+ $filter_last_period = 14 if $filter_last_period < 14;
+ }
+ }
+
+ # form sql queries
- my $now = (time);
- my $bugs_sql = "
+ my $now = (time);
+ my $bugs_sql = "
SELECT bug_id, short_desc, reporter, creation_ts
FROM bugs
WHERE product_id = ?
AND bug_status = 'UNCONFIRMED'";
- if (@component_ids) {
- $bugs_sql .= " AND component_id IN (" . join(',', @component_ids) . ")";
- }
- $bugs_sql .= "
+ if (@component_ids) {
+ $bugs_sql .= " AND component_id IN (" . join(',', @component_ids) . ")";
+ }
+ $bugs_sql .= "
ORDER BY creation_ts
";
- my $comment_count_sql = "
+ my $comment_count_sql = "
SELECT COUNT(*)
FROM longdescs
WHERE bug_id = ?
";
- my $comment_sql = "
+ my $comment_sql = "
SELECT who, bug_when, type, thetext, extra_data
FROM longdescs
WHERE bug_id = ?
";
- if (!Bugzilla->user->is_insider) {
- $comment_sql .= " AND isprivate = 0 ";
- }
- $comment_sql .= "
+ if (!Bugzilla->user->is_insider) {
+ $comment_sql .= " AND isprivate = 0 ";
+ }
+ $comment_sql .= "
ORDER BY bug_when DESC
LIMIT 1
";
- my $attach_sql = "
+ my $attach_sql = "
SELECT description, isprivate
FROM attachments
WHERE attach_id = ?
";
- # work on an initial list of bugs
+ # work on an initial list of bugs
- my $list = $dbh->selectall_arrayref($bugs_sql, undef, $product->id);
- my @bugs;
+ my $list = $dbh->selectall_arrayref($bugs_sql, undef, $product->id);
+ my @bugs;
- # this can be slow to process, resulting in 'service unavailable' errors from zeus
- # so if too many bugs are returned, throw an error
+ # this can be slow to process, resulting in 'service unavailable' errors from zeus
+ # so if too many bugs are returned, throw an error
- if (scalar(@$list) > MAX_NUMBER_BUGS) {
- ThrowUserError('report_too_many_bugs');
- }
+ if (scalar(@$list) > MAX_NUMBER_BUGS) {
+ ThrowUserError('report_too_many_bugs');
+ }
- foreach my $entry (@$list) {
- my ($bug_id, $summary, $reporter_id, $creation_ts) = @$entry;
-
- next unless $user->can_see_bug($bug_id);
-
- # get last comment information
-
- my ($comment_count) = $dbh->selectrow_array($comment_count_sql, undef, $bug_id);
- my ($commenter_id, $comment_ts, $type, $comment, $extra)
- = $dbh->selectrow_array($comment_sql, undef, $bug_id);
- my $commenter = 0;
-
- # apply selected filters
-
- if ($filter_commenter) {
- next if $comment_count <= 1;
-
- if ($filter_commenter_on eq 'reporter') {
- next if $commenter_id != $reporter_id;
-
- } elsif ($filter_commenter_on eq 'noconfirm') {
- $commenter = Bugzilla::User->new({ id => $commenter_id, cache => 1 });
- next if $commenter_id != $reporter_id
- || $commenter->in_group('canconfirm');
-
- } elsif ($filter_commenter_on eq 'is') {
- next if $commenter_id != $filter_commenter_id;
- }
- } else {
- $input->{'commenter'} = '';
- $input->{'commenter_is'} = '';
- }
-
- if ($filter_last) {
- my $comment_time = str2time($comment_ts)
- or next;
- if ($filter_last_period == -1) {
- next if $comment_time >= $filter_last_time;
- } else {
- next if $now - $comment_time <= 60 * 60 * 24 * $filter_last_period;
- }
- } else {
- $input->{'last'} = '';
- $input->{'last_is'} = '';
- }
-
- # get data for attachment comments
-
- if ($comment eq '' && $type == CMT_ATTACHMENT_CREATED) {
- my ($description, $is_private) = $dbh->selectrow_array($attach_sql, undef, $extra);
- next if $is_private && !Bugzilla->user->is_insider;
- $comment = "(Attachment) " . $description;
- }
-
- # truncate long comments
-
- if (length($comment) > 80) {
- $comment = substr($comment, 0, 80) . '...';
- }
-
- # build bug hash for template
-
- my $bug = {};
- $bug->{id} = $bug_id;
- $bug->{summary} = $summary;
- $bug->{reporter} = Bugzilla::User->new({ id => $reporter_id, cache => 1 });
- $bug->{creation_ts} = $creation_ts;
- $bug->{commenter} = $commenter || Bugzilla::User->new({ id => $commenter_id, cache => 1 });
- $bug->{comment_ts} = $comment_ts;
- $bug->{comment} = $comment;
- $bug->{comment_count} = $comment_count;
- push @bugs, $bug;
- }
+ foreach my $entry (@$list) {
+ my ($bug_id, $summary, $reporter_id, $creation_ts) = @$entry;
- @bugs = sort { $b->{comment_ts} cmp $a->{comment_ts} } @bugs;
+ next unless $user->can_see_bug($bug_id);
- $vars->{bugs} = \@bugs;
- } else {
- $input->{action} = '';
- }
+ # get last comment information
- if (!$input->{filter_commenter} && !$input->{filter_last}) {
- $input->{filter_commenter} = 1;
- }
+ my ($comment_count) = $dbh->selectrow_array($comment_count_sql, undef, $bug_id);
+ my ($commenter_id, $comment_ts, $type, $comment, $extra)
+ = $dbh->selectrow_array($comment_sql, undef, $bug_id);
+ my $commenter = 0;
- $vars->{'input'} = $input;
-}
+ # apply selected filters
-sub owners {
- my ($vars, $filter) = @_;
- my $dbh = Bugzilla->dbh;
- my $input = Bugzilla->input_params;
- my $user = Bugzilla->user;
+ if ($filter_commenter) {
+ next if $comment_count <= 1;
- Bugzilla::User::match_field({ 'owner' => {'type' => 'multi'} });
+ if ($filter_commenter_on eq 'reporter') {
+ next if $commenter_id != $reporter_id;
- my @products;
- if (!$input->{product} && $input->{owner}) {
- @products = @{ $user->get_selectable_products };
- }
- else {
- my @product_names = $input->{product} ? ($input->{product}) : DEFAULT_OWNER_PRODUCTS;
- foreach my $name (@product_names) {
- push(@products, Bugzilla::Product->check({ name => $name }));
}
- }
+ elsif ($filter_commenter_on eq 'noconfirm') {
+ $commenter = Bugzilla::User->new({id => $commenter_id, cache => 1});
+ next if $commenter_id != $reporter_id || $commenter->in_group('canconfirm');
- my @component_ids;
- if (@products == 1 && $input->{'component'}) {
- my $ra_components = ref($input->{'component'})
- ? $input->{'component'}
- : [ $input->{'component'} ];
- foreach my $component_name (@$ra_components) {
- my $component = Bugzilla::Component->check({ name => $component_name, product => $products[0] });
- push @component_ids, $component->id;
}
+ elsif ($filter_commenter_on eq 'is') {
+ next if $commenter_id != $filter_commenter_id;
+ }
+ }
+ else {
+ $input->{'commenter'} = '';
+ $input->{'commenter_is'} = '';
+ }
+
+ if ($filter_last) {
+ my $comment_time = str2time($comment_ts) or next;
+ if ($filter_last_period == -1) {
+ next if $comment_time >= $filter_last_time;
+ }
+ else {
+ next if $now - $comment_time <= 60 * 60 * 24 * $filter_last_period;
+ }
+ }
+ else {
+ $input->{'last'} = '';
+ $input->{'last_is'} = '';
+ }
+
+ # get data for attachment comments
+
+ if ($comment eq '' && $type == CMT_ATTACHMENT_CREATED) {
+ my ($description, $is_private)
+ = $dbh->selectrow_array($attach_sql, undef, $extra);
+ next if $is_private && !Bugzilla->user->is_insider;
+ $comment = "(Attachment) " . $description;
+ }
+
+ # truncate long comments
+
+ if (length($comment) > 80) {
+ $comment = substr($comment, 0, 80) . '...';
+ }
+
+ # build bug hash for template
+
+ my $bug = {};
+ $bug->{id} = $bug_id;
+ $bug->{summary} = $summary;
+ $bug->{reporter} = Bugzilla::User->new({id => $reporter_id, cache => 1});
+ $bug->{creation_ts} = $creation_ts;
+ $bug->{commenter}
+ = $commenter || Bugzilla::User->new({id => $commenter_id, cache => 1});
+ $bug->{comment_ts} = $comment_ts;
+ $bug->{comment} = $comment;
+ $bug->{comment_count} = $comment_count;
+ push @bugs, $bug;
}
- my @owner_names = split(/[,;]+/, $input->{owner}) if $input->{owner};
- my @owner_ids;
- foreach my $name (@owner_names) {
- $name = trim($name);
- next unless $name;
- push(@owner_ids, login_to_id($name, THROW_ERROR));
- }
+ @bugs = sort { $b->{comment_ts} cmp $a->{comment_ts} } @bugs;
- my $sql = "SELECT products.name, components.name, components.id, components.triage_owner_id
- FROM components JOIN products ON components.product_id = products.id
- WHERE products.id IN (" . join(',', map { $_->id } @products) . ")";
- if (@component_ids) {
- $sql .= " AND components.id IN (" . join(',', @component_ids) . ")";
- }
- if (@owner_ids) {
- $sql .= " AND components.triage_owner_id IN (" . join(',', @owner_ids) . ")";
- }
- $sql .= " ORDER BY products.name, components.name";
+ $vars->{bugs} = \@bugs;
+ }
+ else {
+ $input->{action} = '';
+ }
- my $rows = $dbh->selectall_arrayref($sql);
+ if (!$input->{filter_commenter} && !$input->{filter_last}) {
+ $input->{filter_commenter} = 1;
+ }
- my $bug_count_sth = $dbh->prepare("
+ $vars->{'input'} = $input;
+}
+
+sub owners {
+ my ($vars, $filter) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
+
+ Bugzilla::User::match_field({'owner' => {'type' => 'multi'}});
+
+ my @products;
+ if (!$input->{product} && $input->{owner}) {
+ @products = @{$user->get_selectable_products};
+ }
+ else {
+ my @product_names
+ = $input->{product} ? ($input->{product}) : DEFAULT_OWNER_PRODUCTS;
+ foreach my $name (@product_names) {
+ push(@products, Bugzilla::Product->check({name => $name}));
+ }
+ }
+
+ my @component_ids;
+ if (@products == 1 && $input->{'component'}) {
+ my $ra_components
+ = ref($input->{'component'})
+ ? $input->{'component'}
+ : [$input->{'component'}];
+ foreach my $component_name (@$ra_components) {
+ my $component = Bugzilla::Component->check(
+ {name => $component_name, product => $products[0]});
+ push @component_ids, $component->id;
+ }
+ }
+
+ my @owner_names = split(/[,;]+/, $input->{owner}) if $input->{owner};
+ my @owner_ids;
+ foreach my $name (@owner_names) {
+ $name = trim($name);
+ next unless $name;
+ push(@owner_ids, login_to_id($name, THROW_ERROR));
+ }
+
+ my $sql
+ = "SELECT products.name, components.name, components.id, components.triage_owner_id
+ FROM components JOIN products ON components.product_id = products.id
+ WHERE products.id IN ("
+ . join(',', map { $_->id } @products) . ")";
+ if (@component_ids) {
+ $sql .= " AND components.id IN (" . join(',', @component_ids) . ")";
+ }
+ if (@owner_ids) {
+ $sql .= " AND components.triage_owner_id IN (" . join(',', @owner_ids) . ")";
+ }
+ $sql .= " ORDER BY products.name, components.name";
+
+ my $rows = $dbh->selectall_arrayref($sql);
+
+ my $bug_count_sth = $dbh->prepare("
SELECT COUNT(bugs.bug_id)
FROM bugs INNER JOIN components AS map_component ON bugs.component_id = map_component.id
INNER JOIN bug_status AS map_bug_status ON bugs.bug_status = map_bug_status.value
@@ -296,55 +314,57 @@ sub owners {
WHERE bugs_1.bug_id = bugs.bug_id AND CONCAT(flagtypes_1.name, flags_1.status) = 'needinfo?')))
AND bugs.component_id = ?");
- my @results;
- foreach my $row (@$rows) {
- my ($product_name, $component_name, $component_id, $triage_owner_id) = @$row;
- my $triage_owner = $triage_owner_id
- ? Bugzilla::User->new({ id => $triage_owner_id, cache => 1 })
- : "";
- my $data = {
- product => $product_name,
- component => $component_name,
- owner => $triage_owner,
- };
- $data->{buglist_url} = 'priority=--&resolution=---&f1=creation_ts&o1=greaterthaneq&v1=2016-06-01'.
- '&f2=flagtypes.name&o2=notequals&v2=needinfo%3F';
- if ($triage_owner) {
- $data->{buglist_url} .= '&f3=triage_owner&o3=equals&v3=' . url_quote($triage_owner->login);
- }
- $bug_count_sth->execute($component_id);
- ($data->{bug_count}) = $bug_count_sth->fetchrow_array();
- push @results, $data;
+ my @results;
+ foreach my $row (@$rows) {
+ my ($product_name, $component_name, $component_id, $triage_owner_id) = @$row;
+ my $triage_owner
+ = $triage_owner_id
+ ? Bugzilla::User->new({id => $triage_owner_id, cache => 1})
+ : "";
+ my $data = {
+ product => $product_name,
+ component => $component_name,
+ owner => $triage_owner,
+ };
+ $data->{buglist_url}
+ = 'priority=--&resolution=---&f1=creation_ts&o1=greaterthaneq&v1=2016-06-01'
+ . '&f2=flagtypes.name&o2=notequals&v2=needinfo%3F';
+ if ($triage_owner) {
+ $data->{buglist_url}
+ .= '&f3=triage_owner&o3=equals&v3=' . url_quote($triage_owner->login);
}
- $vars->{results} = \@results;
-
- my $json_data = { products => [] };
- foreach my $product (@{ $user->get_selectable_products }) {
- my $prod_data = {
- name => $product->name,
- components => [],
- };
- foreach my $component (@{ $product->components }) {
- my $selected = 0;
- if ($input->{product}
- && $input->{product} eq $product->name
- && $input->{component})
- {
- $selected = 1 if (ref $input->{component} && any { $_ eq $component->name } @{ $input->{component} });
- $selected = 1 if (!ref $input->{componet} && $input->{component} eq $component->name);
- }
- my $comp_data = {
- name => $component->name,
- selected => $selected
- };
- push(@{ $prod_data->{components} }, $comp_data);
- }
- push(@{ $json_data->{products} }, $prod_data);
+ $bug_count_sth->execute($component_id);
+ ($data->{bug_count}) = $bug_count_sth->fetchrow_array();
+ push @results, $data;
+ }
+ $vars->{results} = \@results;
+
+ my $json_data = {products => []};
+ foreach my $product (@{$user->get_selectable_products}) {
+ my $prod_data = {name => $product->name, components => [],};
+ foreach my $component (@{$product->components}) {
+ my $selected = 0;
+ if ( $input->{product}
+ && $input->{product} eq $product->name
+ && $input->{component})
+ {
+ $selected = 1
+ if (
+ ref $input->{component} && any { $_ eq $component->name }
+ @{$input->{component}}
+ );
+ $selected = 1
+ if (!ref $input->{componet} && $input->{component} eq $component->name);
+ }
+ my $comp_data = {name => $component->name, selected => $selected};
+ push(@{$prod_data->{components}}, $comp_data);
}
+ push(@{$json_data->{products}}, $prod_data);
+ }
- $vars->{product} = $input->{product};
- $vars->{owner} = $input->{owner};
- $vars->{json_data} = encode_json($json_data);
+ $vars->{product} = $input->{product};
+ $vars->{owner} = $input->{owner};
+ $vars->{json_data} = encode_json($json_data);
}
1;