summaryrefslogtreecommitdiffstats
path: root/extensions/BMO/lib/Reports
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/BMO/lib/Reports')
-rw-r--r--extensions/BMO/lib/Reports/Groups.pm485
-rw-r--r--extensions/BMO/lib/Reports/Internship.pm135
-rw-r--r--extensions/BMO/lib/Reports/ProductSecurity.pm76
-rw-r--r--extensions/BMO/lib/Reports/Recruiting.pm126
-rw-r--r--extensions/BMO/lib/Reports/ReleaseTracking.pm779
-rw-r--r--extensions/BMO/lib/Reports/Triage.pm516
-rw-r--r--extensions/BMO/lib/Reports/UserActivity.pm382
7 files changed, 1202 insertions, 1297 deletions
diff --git a/extensions/BMO/lib/Reports/Groups.pm b/extensions/BMO/lib/Reports/Groups.pm
index ce7df767c..7b395aca9 100644
--- a/extensions/BMO/lib/Reports/Groups.pm
+++ b/extensions/BMO/lib/Reports/Groups.pm
@@ -19,25 +19,24 @@ use Bugzilla::Util qw(trim datetime_from);
use JSON qw(encode_json);
sub admins_report {
- my ($vars) = @_;
- my $dbh = Bugzilla->dbh;
- my $user = Bugzilla->user;
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
- ($user->in_group('editbugs'))
- || ThrowUserError('auth_failure', { group => 'editbugs',
- action => 'run',
- object => 'group_admins' });
+ ($user->in_group('editbugs'))
+ || ThrowUserError('auth_failure',
+ {group => 'editbugs', action => 'run', object => 'group_admins'});
- my @grouplist =
- ($user->in_group('editusers') || $user->in_group('infrasec'))
- ? map { lc($_->name) } Bugzilla::Group->get_all
- : _get_permitted_membership_groups();
+ my @grouplist
+ = ($user->in_group('editusers') || $user->in_group('infrasec'))
+ ? map { lc($_->name) } Bugzilla::Group->get_all
+ : _get_permitted_membership_groups();
- my $groups = join(',', map { $dbh->quote($_) } @grouplist);
+ my $groups = join(',', map { $dbh->quote($_) } @grouplist);
- my $query = "
- SELECT groups.id, " .
- $dbh->sql_group_concat('profiles.userid', "','", 1) . "
+ my $query = "
+ SELECT groups.id, "
+ . $dbh->sql_group_concat('profiles.userid', "','", 1) . "
FROM groups
LEFT JOIN user_group_map
ON user_group_map.group_id = groups.id
@@ -49,271 +48,275 @@ sub admins_report {
AND groups.name IN ($groups)
GROUP BY groups.name";
- my @groups;
- foreach my $row (@{ $dbh->selectall_arrayref($query) }) {
- my $group = Bugzilla::Group->new({ id => shift @$row, cache => 1});
- my @admins;
- if (my $admin_ids = shift @$row) {
- foreach my $uid (split(/,/, $admin_ids)) {
- push(@admins, Bugzilla::User->new({ id => $uid, cache => 1 }));
- }
- }
- push(@groups, { name => $group->name,
- description => $group->description,
- owner => $group->owner,
- admins => \@admins });
+ my @groups;
+ foreach my $row (@{$dbh->selectall_arrayref($query)}) {
+ my $group = Bugzilla::Group->new({id => shift @$row, cache => 1});
+ my @admins;
+ if (my $admin_ids = shift @$row) {
+ foreach my $uid (split(/,/, $admin_ids)) {
+ push(@admins, Bugzilla::User->new({id => $uid, cache => 1}));
+ }
}
+ push(
+ @groups,
+ {
+ name => $group->name,
+ description => $group->description,
+ owner => $group->owner,
+ admins => \@admins
+ }
+ );
+ }
- $vars->{'groups'} = \@groups;
+ $vars->{'groups'} = \@groups;
}
sub membership_report {
- my ($page, $vars) = @_;
- my $dbh = Bugzilla->dbh;
- my $user = Bugzilla->user;
- my $cgi = Bugzilla->cgi;
-
- ($user->in_group('editusers') || $user->in_group('infrasec'))
- || ThrowUserError('auth_failure', { group => 'editusers',
- action => 'run',
- object => 'group_admins' });
-
- my $who = $cgi->param('who');
- if (!defined($who) || $who eq '') {
- if ($page eq 'group_membership.txt') {
- print $cgi->redirect("page.cgi?id=group_membership.html&output=txt");
- exit;
- }
- $vars->{'output'} = $cgi->param('output');
- return;
+ my ($page, $vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+ my $cgi = Bugzilla->cgi;
+
+ ($user->in_group('editusers') || $user->in_group('infrasec'))
+ || ThrowUserError('auth_failure',
+ {group => 'editusers', action => 'run', object => 'group_admins'});
+
+ my $who = $cgi->param('who');
+ if (!defined($who) || $who eq '') {
+ if ($page eq 'group_membership.txt') {
+ print $cgi->redirect("page.cgi?id=group_membership.html&output=txt");
+ exit;
}
+ $vars->{'output'} = $cgi->param('output');
+ return;
+ }
- Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} });
- $who = Bugzilla->input_params->{'who'};
- $who = ref($who) ? $who : [ $who ];
+ Bugzilla::User::match_field({'who' => {'type' => 'multi'}});
+ $who = Bugzilla->input_params->{'who'};
+ $who = ref($who) ? $who : [$who];
- my @users;
- foreach my $login (@$who) {
- my $u = Bugzilla::User->new(login_to_id($login, 1));
+ my @users;
+ foreach my $login (@$who) {
+ my $u = Bugzilla::User->new(login_to_id($login, 1));
- # this is lifted from $user->groups()
- # we need to show which groups are direct and which are inherited
+ # this is lifted from $user->groups()
+ # we need to show which groups are direct and which are inherited
- my $groups_to_check = $dbh->selectcol_arrayref(
- q{SELECT DISTINCT group_id
+ my $groups_to_check = $dbh->selectcol_arrayref(
+ q{SELECT DISTINCT group_id
FROM user_group_map
- WHERE user_id = ? AND isbless = 0}, undef, $u->id);
+ WHERE user_id = ? AND isbless = 0}, undef, $u->id
+ );
- my $rows = $dbh->selectall_arrayref(
- "SELECT DISTINCT grantor_id, member_id
+ my $rows = $dbh->selectall_arrayref(
+ "SELECT DISTINCT grantor_id, member_id
FROM group_group_map
- WHERE grant_type = " . GROUP_MEMBERSHIP);
+ WHERE grant_type = " . GROUP_MEMBERSHIP
+ );
- my %group_membership;
- foreach my $row (@$rows) {
- my ($grantor_id, $member_id) = @$row;
- push (@{ $group_membership{$member_id} }, $grantor_id);
- }
+ my %group_membership;
+ foreach my $row (@$rows) {
+ my ($grantor_id, $member_id) = @$row;
+ push(@{$group_membership{$member_id}}, $grantor_id);
+ }
- my %checked_groups;
- my %direct_groups;
- my %indirect_groups;
- my %groups;
+ my %checked_groups;
+ my %direct_groups;
+ my %indirect_groups;
+ my %groups;
- foreach my $member_id (@$groups_to_check) {
- $direct_groups{$member_id} = 1;
- }
+ foreach my $member_id (@$groups_to_check) {
+ $direct_groups{$member_id} = 1;
+ }
- while (scalar(@$groups_to_check) > 0) {
- my $member_id = shift @$groups_to_check;
- if (!$checked_groups{$member_id}) {
- $checked_groups{$member_id} = 1;
- my $members = $group_membership{$member_id};
- my @new_to_check = grep(!$checked_groups{$_}, @$members);
- push(@$groups_to_check, @new_to_check);
- foreach my $id (@new_to_check) {
- $indirect_groups{$id} = $member_id;
- }
- $groups{$member_id} = 1;
- }
+ while (scalar(@$groups_to_check) > 0) {
+ my $member_id = shift @$groups_to_check;
+ if (!$checked_groups{$member_id}) {
+ $checked_groups{$member_id} = 1;
+ my $members = $group_membership{$member_id};
+ my @new_to_check = grep(!$checked_groups{$_}, @$members);
+ push(@$groups_to_check, @new_to_check);
+ foreach my $id (@new_to_check) {
+ $indirect_groups{$id} = $member_id;
}
+ $groups{$member_id} = 1;
+ }
+ }
- my @groups;
- my $ra_groups = Bugzilla::Group->new_from_list([keys %groups]);
- foreach my $group (@$ra_groups) {
- my $via;
- if ($direct_groups{$group->id}) {
- $via = '';
- } else {
- foreach my $g (@$ra_groups) {
- if ($g->id == $indirect_groups{$group->id}) {
- $via = $g->name;
- last;
- }
- }
- }
- push @groups, {
- name => $group->name,
- desc => $group->description,
- via => $via,
- };
+ my @groups;
+ my $ra_groups = Bugzilla::Group->new_from_list([keys %groups]);
+ foreach my $group (@$ra_groups) {
+ my $via;
+ if ($direct_groups{$group->id}) {
+ $via = '';
+ }
+ else {
+ foreach my $g (@$ra_groups) {
+ if ($g->id == $indirect_groups{$group->id}) {
+ $via = $g->name;
+ last;
+ }
}
-
- push @users, {
- user => $u,
- groups => \@groups,
- };
+ }
+ push @groups, {name => $group->name, desc => $group->description, via => $via,};
}
- $vars->{'who'} = $who;
- $vars->{'users'} = \@users;
+ push @users, {user => $u, groups => \@groups,};
+ }
+
+ $vars->{'who'} = $who;
+ $vars->{'users'} = \@users;
}
sub members_report {
- my ($page, $vars) = @_;
- my $dbh = Bugzilla->dbh;
- my $user = Bugzilla->user;
- my $cgi = Bugzilla->cgi;
-
- ($user->in_group('editbugs'))
- || ThrowUserError('auth_failure', { group => 'editbugs',
- action => 'run',
- object => 'group_admins' });
-
- my $privileged = $user->in_group('editusers') || $user->in_group('infrasec');
- $vars->{privileged} = $privileged;
-
- my @grouplist = $privileged
- ? map { lc($_->name) } Bugzilla::Group->get_all
- : _get_permitted_membership_groups();
-
- my $include_disabled = $cgi->param('include_disabled') ? 1 : 0;
- $vars->{'include_disabled'} = $include_disabled;
-
- # don't allow all groups, to avoid putting pain on the servers
- my @group_names =
- sort
- grep { !/^(?:bz_.+|canconfirm|editbugs|editbugs-team|everyone)$/ }
- @grouplist;
- unshift(@group_names, '');
- $vars->{'groups'} = \@group_names;
-
- # load selected group
- my $group = lc(trim($cgi->param('group') || ''));
- $group = '' unless grep { $_ eq $group } @group_names;
- return if $group eq '';
- my $group_obj = Bugzilla::Group->new({ name => $group });
- $vars->{'group'} = $group_obj;
-
- $vars->{'privileged'} = 1 if ($group_obj->owner && $group_obj->owner->id == $user->id);
-
- my @types;
- my $members = $group_obj->members_complete();
- foreach my $name (sort keys %$members) {
- push @types, {
- name => ($name eq '_direct' ? 'direct' : $name),
- members => _filter_userlist($members->{$name}),
+ my ($page, $vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
+ my $cgi = Bugzilla->cgi;
+
+ ($user->in_group('editbugs'))
+ || ThrowUserError('auth_failure',
+ {group => 'editbugs', action => 'run', object => 'group_admins'});
+
+ my $privileged = $user->in_group('editusers') || $user->in_group('infrasec');
+ $vars->{privileged} = $privileged;
+
+ my @grouplist
+ = $privileged
+ ? map { lc($_->name) } Bugzilla::Group->get_all
+ : _get_permitted_membership_groups();
+
+ my $include_disabled = $cgi->param('include_disabled') ? 1 : 0;
+ $vars->{'include_disabled'} = $include_disabled;
+
+ # don't allow all groups, to avoid putting pain on the servers
+ my @group_names
+ = sort grep { !/^(?:bz_.+|canconfirm|editbugs|editbugs-team|everyone)$/ }
+ @grouplist;
+ unshift(@group_names, '');
+ $vars->{'groups'} = \@group_names;
+
+ # load selected group
+ my $group = lc(trim($cgi->param('group') || ''));
+ $group = '' unless grep { $_ eq $group } @group_names;
+ return if $group eq '';
+ my $group_obj = Bugzilla::Group->new({name => $group});
+ $vars->{'group'} = $group_obj;
+
+ $vars->{'privileged'} = 1
+ if ($group_obj->owner && $group_obj->owner->id == $user->id);
+
+ my @types;
+ my $members = $group_obj->members_complete();
+ foreach my $name (sort keys %$members) {
+ push @types,
+ {
+ name => ($name eq '_direct' ? 'direct' : $name),
+ members => _filter_userlist($members->{$name}),
+ };
+ }
+
+ # make it easy for the template to detect an empty group
+ my $has_members = 0;
+ foreach my $type (@types) {
+ $has_members += scalar(@{$type->{members}});
+ last if $has_members;
+ }
+ @types = () unless $has_members;
+
+ if ($page eq 'group_members.json') {
+ my %users;
+ foreach my $rh (@types) {
+ foreach my $member (@{$rh->{members}}) {
+ my $login = $member->login;
+ if (exists $users{$login}) {
+ push @{$users{$login}->{groups}}, $rh->{name} if $privileged;
}
- }
-
- # make it easy for the template to detect an empty group
- my $has_members = 0;
- foreach my $type (@types) {
- $has_members += scalar(@{ $type->{members} });
- last if $has_members;
- }
- @types = () unless $has_members;
-
- if ($page eq 'group_members.json') {
- my %users;
- foreach my $rh (@types) {
- foreach my $member (@{ $rh->{members} }) {
- my $login = $member->login;
- if (exists $users{$login}) {
- push @{ $users{$login}->{groups} }, $rh->{name} if $privileged;
- }
- else {
- my $rh_user = {
- login => $login,
- membership => $rh->{name} eq 'direct' ? 'direct' : 'indirect',
- rh_name => $rh->{name},
- };
- if ($privileged) {
- $rh_user->{group} = $rh->{name};
- $rh_user->{groups} = [ $rh->{name} ];
- $rh_user->{lastseeon} = $member->last_seen_date;
- $rh_user->{mfa} = $member->mfa;
- $rh_user->{api_key_only} = $member->settings->{api_key_only}->{value} eq 'on'
- ? JSON::true : JSON::false;
- }
- $users{$login} = $rh_user;
- }
- }
+ else {
+ my $rh_user = {
+ login => $login,
+ membership => $rh->{name} eq 'direct' ? 'direct' : 'indirect',
+ rh_name => $rh->{name},
+ };
+ if ($privileged) {
+ $rh_user->{group} = $rh->{name};
+ $rh_user->{groups} = [$rh->{name}];
+ $rh_user->{lastseeon} = $member->last_seen_date;
+ $rh_user->{mfa} = $member->mfa;
+ $rh_user->{api_key_only}
+ = $member->settings->{api_key_only}->{value} eq 'on'
+ ? JSON::true
+ : JSON::false;
+ }
+ $users{$login} = $rh_user;
}
- $vars->{types_json} = JSON->new->pretty->canonical->utf8->encode([ values %users ]);
+ }
}
- else {
- my %users;
- foreach my $rh (@types) {
- foreach my $member (@{ $rh->{members} }) {
- $users{$member->login} = 1 unless exists $users{$member->login};
- }
- }
- $vars->{types} = \@types;
- $vars->{count} = scalar(keys %users);
+ $vars->{types_json}
+ = JSON->new->pretty->canonical->utf8->encode([values %users]);
+ }
+ else {
+ my %users;
+ foreach my $rh (@types) {
+ foreach my $member (@{$rh->{members}}) {
+ $users{$member->login} = 1 unless exists $users{$member->login};
+ }
}
+ $vars->{types} = \@types;
+ $vars->{count} = scalar(keys %users);
+ }
}
sub _filter_userlist {
- my ($list, $include_disabled) = @_;
- $list = [ grep { $_->is_enabled } @$list ] unless $include_disabled;
- my $now = DateTime->now();
- my $never = DateTime->from_epoch( epoch => 0 );
- foreach my $user (@$list) {
- my $last_seen = $user->last_seen_date ? datetime_from($user->last_seen_date) : $never;
- $user->{last_seen_days} = sprintf(
- '%.0f',
- $now->subtract_datetime_absolute($last_seen)->delta_seconds / (28 * 60 * 60));
- }
- return [ sort { lc($a->identity) cmp lc($b->identity) } @$list ];
+ my ($list, $include_disabled) = @_;
+ $list = [grep { $_->is_enabled } @$list] unless $include_disabled;
+ my $now = DateTime->now();
+ my $never = DateTime->from_epoch(epoch => 0);
+ foreach my $user (@$list) {
+ my $last_seen
+ = $user->last_seen_date ? datetime_from($user->last_seen_date) : $never;
+ $user->{last_seen_days} = sprintf('%.0f',
+ $now->subtract_datetime_absolute($last_seen)->delta_seconds / (28 * 60 * 60));
+ }
+ return [sort { lc($a->identity) cmp lc($b->identity) } @$list];
}
# Groups that any user with editbugs can see the membership or admin lists for.
# Transparency FTW.
sub _get_permitted_membership_groups {
- my $user = Bugzilla->user;
-
- # Default publicly viewable groups
- my %default_public_groups = map { $_ => 1 } qw(
- bugzilla-approvers
- bugzilla-reviewers
- can_restrict_comments
- community-it-team
- mozilla-employee-confidential
- mozilla-foundation-confidential
- mozilla-reps
- qa-approvers
- );
-
- # We add the group to the permitted list if:
- # 1. it is a drivers group - this gives us a little
- # future-proofing
- # 2. it is a one of the default public groups
- # 3. the user is the group's owner
- # 4. or the user can bless others into the group
- my @permitted_groups;
- foreach my $group (Bugzilla::Group->get_all) {
- my $name = $group->name;
- if ($name =~ /-drivers$/
- || exists $default_public_groups{$name}
- || ($group->owner && $group->owner->id == $user->id)
- || $user->can_bless($group->id))
- {
- push(@permitted_groups, $name);
- }
+ my $user = Bugzilla->user;
+
+ # Default publicly viewable groups
+ my %default_public_groups = map { $_ => 1 } qw(
+ bugzilla-approvers
+ bugzilla-reviewers
+ can_restrict_comments
+ community-it-team
+ mozilla-employee-confidential
+ mozilla-foundation-confidential
+ mozilla-reps
+ qa-approvers
+ );
+
+ # We add the group to the permitted list if:
+ # 1. it is a drivers group - this gives us a little
+ # future-proofing
+ # 2. it is a one of the default public groups
+ # 3. the user is the group's owner
+ # 4. or the user can bless others into the group
+ my @permitted_groups;
+ foreach my $group (Bugzilla::Group->get_all) {
+ my $name = $group->name;
+ if ( $name =~ /-drivers$/
+ || exists $default_public_groups{$name}
+ || ($group->owner && $group->owner->id == $user->id)
+ || $user->can_bless($group->id))
+ {
+ push(@permitted_groups, $name);
}
+ }
- return @permitted_groups;
+ return @permitted_groups;
}
1;
diff --git a/extensions/BMO/lib/Reports/Internship.pm b/extensions/BMO/lib/Reports/Internship.pm
index 2dfa583a6..f9ad1a578 100644
--- a/extensions/BMO/lib/Reports/Internship.pm
+++ b/extensions/BMO/lib/Reports/Internship.pm
@@ -17,33 +17,30 @@ use Bugzilla::Product;
use Bugzilla::Component;
sub report {
- my ($vars) = @_;
- my $user = Bugzilla->user;
-
- $user->in_group('hr')
- || ThrowUserError('auth_failure', { group => 'hr',
- action => 'run',
- object => 'internship_dashboard' });
-
- my $product = Bugzilla::Product->check({ name => 'Recruiting', cache => 1 });
- my $component = Bugzilla::Component->new({ product => $product, name => 'Intern', cache => 1 });
-
- # find all open internship bugs
- my $bugs = Bugzilla::Bug->match({
- product_id => $product->id,
- component_id => $component->id,
- resolution => '',
- });
-
- # filter bugs based on visibility and re-bless
- $user->visible_bugs($bugs);
- $bugs = [
- map { bless($_, 'InternshipBug') }
- grep { $user->can_see_bug($_->id) }
- @$bugs
- ];
-
- $vars->{bugs} = $bugs;
+ my ($vars) = @_;
+ my $user = Bugzilla->user;
+
+ $user->in_group('hr')
+ || ThrowUserError('auth_failure',
+ {group => 'hr', action => 'run', object => 'internship_dashboard'});
+
+ my $product = Bugzilla::Product->check({name => 'Recruiting', cache => 1});
+ my $component = Bugzilla::Component->new(
+ {product => $product, name => 'Intern', cache => 1});
+
+ # find all open internship bugs
+ my $bugs = Bugzilla::Bug->match({
+ product_id => $product->id,
+ component_id => $component->id,
+ resolution => '',
+ });
+
+ # filter bugs based on visibility and re-bless
+ $user->visible_bugs($bugs);
+ $bugs = [map { bless($_, 'InternshipBug') }
+ grep { $user->can_see_bug($_->id) } @$bugs];
+
+ $vars->{bugs} = $bugs;
}
1;
@@ -58,64 +55,62 @@ use Bugzilla::Comment;
use Bugzilla::Util qw(trim);
sub _extract {
- my ($self) = @_;
- return if exists $self->{internship_data};
- $self->{internship_data} = {};
-
- # we only need the first comment
- my $comment = Bugzilla::Comment->match({
- bug_id => $self->id,
- LIMIT => 1,
- })->[0]->body;
-
- # extract just what we need
- # changing the comment will break this
-
- if ($comment =~ /Hiring Manager:\s+(.+)\nTeam:\n/s) {
- $self->{internship_data}->{hiring_manager} = trim($1);
- }
- if ($comment =~ /\nVP Authority:\s+(.+)\nProduct Line:\n/s) {
- $self->{internship_data}->{scvp} = trim($1);
- }
- if ($comment =~ /\nProduct Line:\s+(.+)\nLevel 1/s) {
- $self->{internship_data}->{product_line} = trim($1);
- }
- if ($comment =~ /\nBusiness Need:\s+(.+)\nPotential Project:\n/s) {
- $self->{internship_data}->{business_need} = trim($1);
- }
- if ($comment =~ /\nName:\s+(.+)$/s) {
- $self->{internship_data}->{intern_name} = trim($1);
- }
+ my ($self) = @_;
+ return if exists $self->{internship_data};
+ $self->{internship_data} = {};
+
+ # we only need the first comment
+ my $comment
+ = Bugzilla::Comment->match({bug_id => $self->id, LIMIT => 1,})->[0]->body;
+
+ # extract just what we need
+ # changing the comment will break this
+
+ if ($comment =~ /Hiring Manager:\s+(.+)\nTeam:\n/s) {
+ $self->{internship_data}->{hiring_manager} = trim($1);
+ }
+ if ($comment =~ /\nVP Authority:\s+(.+)\nProduct Line:\n/s) {
+ $self->{internship_data}->{scvp} = trim($1);
+ }
+ if ($comment =~ /\nProduct Line:\s+(.+)\nLevel 1/s) {
+ $self->{internship_data}->{product_line} = trim($1);
+ }
+ if ($comment =~ /\nBusiness Need:\s+(.+)\nPotential Project:\n/s) {
+ $self->{internship_data}->{business_need} = trim($1);
+ }
+ if ($comment =~ /\nName:\s+(.+)$/s) {
+ $self->{internship_data}->{intern_name} = trim($1);
+ }
}
sub hiring_manager {
- my ($self) = @_;
- $self->_extract();
- return $self->{internship_data}->{hiring_manager};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{internship_data}->{hiring_manager};
}
sub scvp {
- my ($self) = @_;
- $self->_extract();
- return $self->{internship_data}->{scvp};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{internship_data}->{scvp};
}
sub business_need {
- my ($self) = @_;
- $self->_extract();
- return $self->{internship_data}->{business_need};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{internship_data}->{business_need};
}
sub product_line {
- my ($self) = @_;
- $self->_extract();
- return $self->{internship_data}->{product_line};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{internship_data}->{product_line};
}
sub intern_name {
- my ($self) = @_;
- $self->_extract();
- return $self->{internship_data}->{intern_name};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{internship_data}->{intern_name};
}
1;
diff --git a/extensions/BMO/lib/Reports/ProductSecurity.pm b/extensions/BMO/lib/Reports/ProductSecurity.pm
index e7ccda171..fb773cd93 100644
--- a/extensions/BMO/lib/Reports/ProductSecurity.pm
+++ b/extensions/BMO/lib/Reports/ProductSecurity.pm
@@ -16,54 +16,54 @@ use Bugzilla::Error;
use Bugzilla::Product;
sub report {
- my ($vars) = @_;
- my $user = Bugzilla->user;
+ my ($vars) = @_;
+ my $user = Bugzilla->user;
- ($user->in_group('admin') || $user->in_group('infrasec'))
- || ThrowUserError('auth_failure', { group => 'admin',
- action => 'run',
- object => 'product_security' });
+ ($user->in_group('admin') || $user->in_group('infrasec'))
+ || ThrowUserError('auth_failure',
+ {group => 'admin', action => 'run', object => 'product_security'});
- my $moco = Bugzilla::Group->new({ name => 'mozilla-employee-confidential' })
- or return;
+ my $moco = Bugzilla::Group->new({name => 'mozilla-employee-confidential'})
+ or return;
- my $products = [];
- foreach my $product (@{ Bugzilla::Product->match({}) }) {
- my $default_group = $product->default_security_group_obj;
- my $group_controls = $product->group_controls();
+ my $products = [];
+ foreach my $product (@{Bugzilla::Product->match({})}) {
+ my $default_group = $product->default_security_group_obj;
+ my $group_controls = $product->group_controls();
- my $item = {
- name => $product->name,
- default_security_group => $product->default_security_group,
- group_visibility => 'None/None',
- moco => exists $group_controls->{$moco->id},
- };
+ my $item = {
+ name => $product->name,
+ default_security_group => $product->default_security_group,
+ group_visibility => 'None/None',
+ moco => exists $group_controls->{$moco->id},
+ };
- if ($default_group) {
- if (my $control = $group_controls->{$default_group->id}) {
- $item->{group_visibility} = control_to_string($control->{membercontrol}) .
- '/' . control_to_string($control->{othercontrol});
- }
- }
+ if ($default_group) {
+ if (my $control = $group_controls->{$default_group->id}) {
+ $item->{group_visibility} = control_to_string($control->{membercontrol}) . '/'
+ . control_to_string($control->{othercontrol});
+ }
+ }
- $item->{group_problem} = $default_group ? '' : "Invalid group " . $product->default_security_group;
- $item->{visibility_problem} = 'Default security group should be Shown/Shown'
- if ($item->{group_visibility} ne 'Shown/Shown')
- && ($item->{group_visibility} ne 'Mandatory/Mandatory')
- && ($item->{group_visibility} ne 'Default/Default');
+ $item->{group_problem}
+ = $default_group ? '' : "Invalid group " . $product->default_security_group;
+ $item->{visibility_problem} = 'Default security group should be Shown/Shown'
+ if ($item->{group_visibility} ne 'Shown/Shown')
+ && ($item->{group_visibility} ne 'Mandatory/Mandatory')
+ && ($item->{group_visibility} ne 'Default/Default');
- push @$products, $item;
- }
- $vars->{products} = $products;
+ push @$products, $item;
+ }
+ $vars->{products} = $products;
}
sub control_to_string {
- my ($control) = @_;
- return 'NA' if $control == CONTROLMAPNA;
- return 'Shown' if $control == CONTROLMAPSHOWN;
- return 'Default' if $control == CONTROLMAPDEFAULT;
- return 'Mandatory' if $control == CONTROLMAPMANDATORY;
- return '';
+ my ($control) = @_;
+ return 'NA' if $control == CONTROLMAPNA;
+ return 'Shown' if $control == CONTROLMAPSHOWN;
+ return 'Default' if $control == CONTROLMAPDEFAULT;
+ return 'Mandatory' if $control == CONTROLMAPMANDATORY;
+ return '';
}
1;
diff --git a/extensions/BMO/lib/Reports/Recruiting.pm b/extensions/BMO/lib/Reports/Recruiting.pm
index 39eb8327d..c35b0cbff 100644
--- a/extensions/BMO/lib/Reports/Recruiting.pm
+++ b/extensions/BMO/lib/Reports/Recruiting.pm
@@ -17,33 +17,30 @@ use Bugzilla::Product;
use Bugzilla::Component;
sub report {
- my ($vars) = @_;
- my $user = Bugzilla->user;
-
- $user->in_group('hr')
- || ThrowUserError('auth_failure', { group => 'hr',
- action => 'run',
- object => 'recruiting_dashboard' });
-
- my $product = Bugzilla::Product->check({ name => 'Recruiting', cache => 1 });
- my $component = Bugzilla::Component->new({ product => $product, name => 'General', cache => 1 });
-
- # find all open recruiting bugs
- my $bugs = Bugzilla::Bug->match({
- product_id => $product->id,
- component_id => $component->id,
- resolution => '',
- });
-
- # filter bugs based on visibility and re-bless
- $user->visible_bugs($bugs);
- $bugs = [
- map { bless($_, 'RecruitingBug') }
- grep { $user->can_see_bug($_->id) }
- @$bugs
- ];
-
- $vars->{bugs} = $bugs;
+ my ($vars) = @_;
+ my $user = Bugzilla->user;
+
+ $user->in_group('hr')
+ || ThrowUserError('auth_failure',
+ {group => 'hr', action => 'run', object => 'recruiting_dashboard'});
+
+ my $product = Bugzilla::Product->check({name => 'Recruiting', cache => 1});
+ my $component = Bugzilla::Component->new(
+ {product => $product, name => 'General', cache => 1});
+
+ # find all open recruiting bugs
+ my $bugs = Bugzilla::Bug->match({
+ product_id => $product->id,
+ component_id => $component->id,
+ resolution => '',
+ });
+
+ # filter bugs based on visibility and re-bless
+ $user->visible_bugs($bugs);
+ $bugs = [map { bless($_, 'RecruitingBug') }
+ grep { $user->can_see_bug($_->id) } @$bugs];
+
+ $vars->{bugs} = $bugs;
}
1;
@@ -58,55 +55,56 @@ use Bugzilla::Comment;
use Bugzilla::Util qw(trim);
sub _extract {
- my ($self) = @_;
- return if exists $self->{recruitment_data};
- $self->{recruitment_data} = {};
-
- # we only need the first comment
- my $comment = Bugzilla::Comment->match({
- bug_id => $self->id,
- LIMIT => 1,
- })->[0]->body;
-
- # extract just what we need
- # changing the comment will break this
-
- if ($comment =~ /\nHiring Manager:\s+(.+)VP Authority:\n/s) {
- $self->{recruitment_data}->{hiring_manager} = trim($1);
- }
- if ($comment =~ /\nVP Authority:\s+(.+)HRBP:\n/s) {
- $self->{recruitment_data}->{scvp} = trim($1);
- }
- if ($comment =~ /\nWhat part of your strategic plan does this role impact\?\s+(.+)Why is this critical for success\?\n/s) {
- $self->{recruitment_data}->{strategic_plan} = trim($1);
- }
- if ($comment =~ /\nWhy is this critical for success\?\s+(.+)$/s) {
- $self->{recruitment_data}->{why_critical} = trim($1);
- }
+ my ($self) = @_;
+ return if exists $self->{recruitment_data};
+ $self->{recruitment_data} = {};
+
+ # we only need the first comment
+ my $comment
+ = Bugzilla::Comment->match({bug_id => $self->id, LIMIT => 1,})->[0]->body;
+
+ # extract just what we need
+ # changing the comment will break this
+
+ if ($comment =~ /\nHiring Manager:\s+(.+)VP Authority:\n/s) {
+ $self->{recruitment_data}->{hiring_manager} = trim($1);
+ }
+ if ($comment =~ /\nVP Authority:\s+(.+)HRBP:\n/s) {
+ $self->{recruitment_data}->{scvp} = trim($1);
+ }
+ if ($comment
+ =~ /\nWhat part of your strategic plan does this role impact\?\s+(.+)Why is this critical for success\?\n/s
+ )
+ {
+ $self->{recruitment_data}->{strategic_plan} = trim($1);
+ }
+ if ($comment =~ /\nWhy is this critical for success\?\s+(.+)$/s) {
+ $self->{recruitment_data}->{why_critical} = trim($1);
+ }
}
sub hiring_manager {
- my ($self) = @_;
- $self->_extract();
- return $self->{recruitment_data}->{hiring_manager};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{recruitment_data}->{hiring_manager};
}
sub scvp {
- my ($self) = @_;
- $self->_extract();
- return $self->{recruitment_data}->{scvp};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{recruitment_data}->{scvp};
}
sub strategic_plan {
- my ($self) = @_;
- $self->_extract();
- return $self->{recruitment_data}->{strategic_plan};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{recruitment_data}->{strategic_plan};
}
sub why_critical {
- my ($self) = @_;
- $self->_extract();
- return $self->{recruitment_data}->{why_critical};
+ my ($self) = @_;
+ $self->_extract();
+ return $self->{recruitment_data}->{why_critical};
}
1;
diff --git a/extensions/BMO/lib/Reports/ReleaseTracking.pm b/extensions/BMO/lib/Reports/ReleaseTracking.pm
index 9fba1e14b..38a07aee7 100644
--- a/extensions/BMO/lib/Reports/ReleaseTracking.pm
+++ b/extensions/BMO/lib/Reports/ReleaseTracking.pm
@@ -21,496 +21,381 @@ use JSON qw(-convert_blessed_universally);
use List::MoreUtils qw(uniq);
use constant DATE_RANGES => [
- {
- value => '20160126-20160307',
- label => '2016-01-26 and 2016-03-07'
- },
- {
- value => '20151215-20160125',
- label => '2015-12-15 and 2016-01-25'
- },
- {
- value => '20151103-20151214',
- label => '2015-11-03 and 2015-12-14'
- },
- {
- value => '20150922-20151102',
- label => '2015-09-22 and 2015-11-02'
- },
- {
- value => '20150811-20150921',
- label => '2015-08-11 and 2015-09-21'
- },
- {
- value => '20150630-20150810',
- label => '2015-06-30 and 2015-08-10'
- },
- {
- value => '20150512-20150629',
- label => '2015-05-12 and 2015-06-29'
- },
- {
- value => '20150331-20150511',
- label => '2015-03-31 and 2015-05-11'
- },
- {
- value => '20150224-20150330',
- label => '2015-02-24 and 2015-03-30'
- },
- {
- value => '20150113-20150223',
- label => '2015-01-13 and 2015-02-23'
- },
- {
- value => '20141111-20141222',
- label => '2014-11-11 and 2014-12-22'
- },
- {
- value => '20140930-20141110',
- label => '2014-09-30 and 2014-11-10'
- },
- {
- value => '20140819-20140929',
- label => '2014-08-19 and 2014-09-29'
- },
- {
- value => '20140708-20140818',
- label => '2014-07-08 and 2014-08-18'
- },
- {
- value => '20140527-20140707',
- label => '2014-05-27 and 2014-07-07'
- },
- {
- value => '20140415-20140526',
- label => '2014-04-15 and 2014-05-26'
- },
- {
- value => '20140304-20140414',
- label => '2014-03-04 and 2014-04-14'
- },
- {
- value => '20140121-20140303',
- label => '2014-01-21 and 2014-03-03'
- },
- {
- value => '20131210-20140120',
- label => '2013-12-10 and 2014-01-20'
- },
- {
- value => '20131029-20131209',
- label => '2013-10-29 and 2013-12-09'
- },
- {
- value => '20130917-20131028',
- label => '2013-09-17 and 2013-10-28'
- },
- {
- value => '20130806-20130916',
- label => '2013-08-06 and 2013-09-16'
- },
- {
- value => '20130625-20130805',
- label => '2013-06-25 and 2013-08-05'
- },
- {
- value => '20130514-20130624',
- label => '2013-05-14 and 2013-06-24'
- },
- {
- value => '20130402-20130513',
- label => '2013-04-02 and 2013-05-13'
- },
- {
- value => '20130219-20130401',
- label => '2013-02-19 and 2013-04-01'
- },
- {
- value => '20130108-20130218',
- label => '2013-01-08 and 2013-02-18'
- },
- {
- value => '20121120-20130107',
- label => '2012-11-20 and 2013-01-07'
- },
- {
- value => '20121009-20121119',
- label => '2012-10-09 and 2012-11-19'
- },
- {
- value => '20120828-20121008',
- label => '2012-08-28 and 2012-10-08'
- },
- {
- value => '20120717-20120827',
- label => '2012-07-17 and 2012-08-27'
- },
- {
- value => '20120605-20120716',
- label => '2012-06-05 and 2012-07-16'
- },
- {
- value => '20120424-20120604',
- label => '2012-04-24 and 2012-06-04'
- },
- {
- value => '20120313-20120423',
- label => '2012-03-13 and 2012-04-23'
- },
- {
- value => '20120131-20120312',
- label => '2012-01-31 and 2012-03-12'
- },
- {
- value => '20111220-20120130',
- label => '2011-12-20 and 2012-01-30'
- },
- {
- value => '20111108-20111219',
- label => '2011-11-08 and 2011-12-19'
- },
- {
- value => '20110927-20111107',
- label => '2011-09-27 and 2011-11-07'
- },
- {
- value => '20110816-20110926',
- label => '2011-08-16 and 2011-09-26'
- },
- {
- value => '*',
- label => 'Anytime'
- }
+ {value => '20160126-20160307', label => '2016-01-26 and 2016-03-07'},
+ {value => '20151215-20160125', label => '2015-12-15 and 2016-01-25'},
+ {value => '20151103-20151214', label => '2015-11-03 and 2015-12-14'},
+ {value => '20150922-20151102', label => '2015-09-22 and 2015-11-02'},
+ {value => '20150811-20150921', label => '2015-08-11 and 2015-09-21'},
+ {value => '20150630-20150810', label => '2015-06-30 and 2015-08-10'},
+ {value => '20150512-20150629', label => '2015-05-12 and 2015-06-29'},
+ {value => '20150331-20150511', label => '2015-03-31 and 2015-05-11'},
+ {value => '20150224-20150330', label => '2015-02-24 and 2015-03-30'},
+ {value => '20150113-20150223', label => '2015-01-13 and 2015-02-23'},
+ {value => '20141111-20141222', label => '2014-11-11 and 2014-12-22'},
+ {value => '20140930-20141110', label => '2014-09-30 and 2014-11-10'},
+ {value => '20140819-20140929', label => '2014-08-19 and 2014-09-29'},
+ {value => '20140708-20140818', label => '2014-07-08 and 2014-08-18'},
+ {value => '20140527-20140707', label => '2014-05-27 and 2014-07-07'},
+ {value => '20140415-20140526', label => '2014-04-15 and 2014-05-26'},
+ {value => '20140304-20140414', label => '2014-03-04 and 2014-04-14'},
+ {value => '20140121-20140303', label => '2014-01-21 and 2014-03-03'},
+ {value => '20131210-20140120', label => '2013-12-10 and 2014-01-20'},
+ {value => '20131029-20131209', label => '2013-10-29 and 2013-12-09'},
+ {value => '20130917-20131028', label => '2013-09-17 and 2013-10-28'},
+ {value => '20130806-20130916', label => '2013-08-06 and 2013-09-16'},
+ {value => '20130625-20130805', label => '2013-06-25 and 2013-08-05'},
+ {value => '20130514-20130624', label => '2013-05-14 and 2013-06-24'},
+ {value => '20130402-20130513', label => '2013-04-02 and 2013-05-13'},
+ {value => '20130219-20130401', label => '2013-02-19 and 2013-04-01'},
+ {value => '20130108-20130218', label => '2013-01-08 and 2013-02-18'},
+ {value => '20121120-20130107', label => '2012-11-20 and 2013-01-07'},
+ {value => '20121009-20121119', label => '2012-10-09 and 2012-11-19'},
+ {value => '20120828-20121008', label => '2012-08-28 and 2012-10-08'},
+ {value => '20120717-20120827', label => '2012-07-17 and 2012-08-27'},
+ {value => '20120605-20120716', label => '2012-06-05 and 2012-07-16'},
+ {value => '20120424-20120604', label => '2012-04-24 and 2012-06-04'},
+ {value => '20120313-20120423', label => '2012-03-13 and 2012-04-23'},
+ {value => '20120131-20120312', label => '2012-01-31 and 2012-03-12'},
+ {value => '20111220-20120130', label => '2011-12-20 and 2012-01-30'},
+ {value => '20111108-20111219', label => '2011-11-08 and 2011-12-19'},
+ {value => '20110927-20111107', label => '2011-09-27 and 2011-11-07'},
+ {value => '20110816-20110926', label => '2011-08-16 and 2011-09-26'},
+ {value => '*', label => 'Anytime'}
];
sub report {
- my ($vars) = @_;
- my $dbh = Bugzilla->dbh;
- my $input = Bugzilla->input_params;
- my $user = Bugzilla->user;
-
- my @flag_names = qw(
- approval-mozilla-release
- approval-mozilla-beta
- approval-mozilla-aurora
- approval-mozilla-central
- approval-comm-release
- approval-comm-beta
- approval-comm-aurora
- approval-calendar-release
- approval-calendar-beta
- approval-calendar-aurora
- approval-mozilla-esr10
- );
-
- my @flags_json;
- my @fields_json;
- my @products_json;
-
- #
- # tracking flags
- #
-
- my $all_products = $user->get_selectable_products;
- my @usable_products;
-
- # build list of flags and their matching products
-
- my @invalid_flag_names;
- foreach my $flag_name (@flag_names) {
- # grab all matching flag_types
- my @flag_types = @{Bugzilla::FlagType::match({ name => $flag_name, is_active => 1 })};
-
- # remove invalid flags
- if (!@flag_types) {
- push @invalid_flag_names, $flag_name;
- next;
- }
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+ my $user = Bugzilla->user;
+
+ my @flag_names = qw(
+ approval-mozilla-release
+ approval-mozilla-beta
+ approval-mozilla-aurora
+ approval-mozilla-central
+ approval-comm-release
+ approval-comm-beta
+ approval-comm-aurora
+ approval-calendar-release
+ approval-calendar-beta
+ approval-calendar-aurora
+ approval-mozilla-esr10
+ );
+
+ my @flags_json;
+ my @fields_json;
+ my @products_json;
+
+ #
+ # tracking flags
+ #
+
+ my $all_products = $user->get_selectable_products;
+ my @usable_products;
+
+ # build list of flags and their matching products
+
+ my @invalid_flag_names;
+ foreach my $flag_name (@flag_names) {
+
+ # grab all matching flag_types
+ my @flag_types
+ = @{Bugzilla::FlagType::match({name => $flag_name, is_active => 1})};
+
+ # remove invalid flags
+ if (!@flag_types) {
+ push @invalid_flag_names, $flag_name;
+ next;
+ }
- # we need a list of products, based on inclusions/exclusions
- my @products;
- my %flag_types;
- foreach my $flag_type (@flag_types) {
- $flag_types{$flag_type->name} = $flag_type->id;
- my $has_all = 0;
- my @exclusion_ids;
- my @inclusion_ids;
- foreach my $flag_type (@flag_types) {
- if (scalar keys %{$flag_type->inclusions}) {
- my $inclusions = $flag_type->inclusions;
- foreach my $key (keys %$inclusions) {
- push @inclusion_ids, ($inclusions->{$key} =~ /^(\d+)/);
- }
- } elsif (scalar keys %{$flag_type->exclusions}) {
- my $exclusions = $flag_type->exclusions;
- foreach my $key (keys %$exclusions) {
- push @exclusion_ids, ($exclusions->{$key} =~ /^(\d+)/);
- }
- } else {
- $has_all = 1;
- last;
- }
- }
-
- if ($has_all) {
- push @products, @$all_products;
- } elsif (scalar @exclusion_ids) {
- push @products, @$all_products;
- foreach my $exclude_id (uniq @exclusion_ids) {
- @products = grep { $_->id != $exclude_id } @products;
- }
- } else {
- foreach my $include_id (uniq @inclusion_ids) {
- push @products, grep { $_->id == $include_id } @$all_products;
- }
- }
+ # we need a list of products, based on inclusions/exclusions
+ my @products;
+ my %flag_types;
+ foreach my $flag_type (@flag_types) {
+ $flag_types{$flag_type->name} = $flag_type->id;
+ my $has_all = 0;
+ my @exclusion_ids;
+ my @inclusion_ids;
+ foreach my $flag_type (@flag_types) {
+ if (scalar keys %{$flag_type->inclusions}) {
+ my $inclusions = $flag_type->inclusions;
+ foreach my $key (keys %$inclusions) {
+ push @inclusion_ids, ($inclusions->{$key} =~ /^(\d+)/);
+ }
}
- @products = uniq @products;
- push @usable_products, @products;
- my @product_ids = map { $_->id } sort { lc($a->name) cmp lc($b->name) } @products;
-
- push @flags_json, {
- name => $flag_name,
- id => $flag_types{$flag_name} || 0,
- products => \@product_ids,
- fields => [],
- };
- }
- foreach my $flag_name (@invalid_flag_names) {
- @flag_names = grep { $_ ne $flag_name } @flag_names;
- }
- @usable_products = uniq @usable_products;
-
- # build a list of tracking flags for each product
- # also build the list of all fields
-
- my @unlink_products;
- foreach my $product (@usable_products) {
- my @fields =
- sort { $a->sortkey <=> $b->sortkey }
- grep { is_active_status_field($_) }
- Bugzilla->active_custom_fields({ product => $product });
- my @field_ids = map { $_->id } @fields;
- if (!scalar @fields) {
- push @unlink_products, $product;
- next;
+ elsif (scalar keys %{$flag_type->exclusions}) {
+ my $exclusions = $flag_type->exclusions;
+ foreach my $key (keys %$exclusions) {
+ push @exclusion_ids, ($exclusions->{$key} =~ /^(\d+)/);
+ }
}
-
- # product
- push @products_json, {
- name => $product->name,
- id => $product->id,
- fields => \@field_ids,
- };
-
- # add fields to flags
- foreach my $rh (@flags_json) {
- if (grep { $_ eq $product->id } @{$rh->{products}}) {
- push @{$rh->{fields}}, @field_ids;
- }
+ else {
+ $has_all = 1;
+ last;
}
-
- # add fields to fields_json
- foreach my $field (@fields) {
- my $existing = 0;
- foreach my $rh (@fields_json) {
- if ($rh->{id} == $field->id) {
- $existing = 1;
- last;
- }
- }
- if (!$existing) {
- push @fields_json, {
- name => $field->name,
- desc => $field->description,
- id => $field->id,
- };
- }
+ }
+
+ if ($has_all) {
+ push @products, @$all_products;
+ }
+ elsif (scalar @exclusion_ids) {
+ push @products, @$all_products;
+ foreach my $exclude_id (uniq @exclusion_ids) {
+ @products = grep { $_->id != $exclude_id } @products;
}
+ }
+ else {
+ foreach my $include_id (uniq @inclusion_ids) {
+ push @products, grep { $_->id == $include_id } @$all_products;
+ }
+ }
}
- foreach my $rh (@flags_json) {
- my @fields = uniq @{$rh->{fields}};
- $rh->{fields} = \@fields;
+ @products = uniq @products;
+ push @usable_products, @products;
+ my @product_ids
+ = map { $_->id } sort { lc($a->name) cmp lc($b->name) } @products;
+
+ push @flags_json,
+ {
+ name => $flag_name,
+ id => $flag_types{$flag_name} || 0,
+ products => \@product_ids,
+ fields => [],
+ };
+ }
+ foreach my $flag_name (@invalid_flag_names) {
+ @flag_names = grep { $_ ne $flag_name } @flag_names;
+ }
+ @usable_products = uniq @usable_products;
+
+ # build a list of tracking flags for each product
+ # also build the list of all fields
+
+ my @unlink_products;
+ foreach my $product (@usable_products) {
+ my @fields
+ = sort { $a->sortkey <=> $b->sortkey }
+ grep { is_active_status_field($_) }
+ Bugzilla->active_custom_fields({product => $product});
+ my @field_ids = map { $_->id } @fields;
+ if (!scalar @fields) {
+ push @unlink_products, $product;
+ next;
}
- # remove products which aren't linked with status fields
+ # product
+ push @products_json,
+ {name => $product->name, id => $product->id, fields => \@field_ids,};
+ # add fields to flags
foreach my $rh (@flags_json) {
- my @product_ids;
- foreach my $id (@{$rh->{products}}) {
- unless (grep { $_->id == $id } @unlink_products) {
- push @product_ids, $id;
- }
- $rh->{products} = \@product_ids;
+ if (grep { $_ eq $product->id } @{$rh->{products}}) {
+ push @{$rh->{fields}}, @field_ids;
+ }
+ }
+
+ # add fields to fields_json
+ foreach my $field (@fields) {
+ my $existing = 0;
+ foreach my $rh (@fields_json) {
+ if ($rh->{id} == $field->id) {
+ $existing = 1;
+ last;
}
+ }
+ if (!$existing) {
+ push @fields_json,
+ {name => $field->name, desc => $field->description, id => $field->id,};
+ }
}
+ }
+ foreach my $rh (@flags_json) {
+ my @fields = uniq @{$rh->{fields}};
+ $rh->{fields} = \@fields;
+ }
+
+ # remove products which aren't linked with status fields
+
+ foreach my $rh (@flags_json) {
+ my @product_ids;
+ foreach my $id (@{$rh->{products}}) {
+ unless (grep { $_->id == $id } @unlink_products) {
+ push @product_ids, $id;
+ }
+ $rh->{products} = \@product_ids;
+ }
+ }
- #
- # run report
- #
+ #
+ # run report
+ #
- if ($input->{q} && !$input->{edit}) {
- my $q = _parse_query($input->{q});
+ if ($input->{q} && !$input->{edit}) {
+ my $q = _parse_query($input->{q});
- my @where;
- my @params;
- my $query = "
+ my @where;
+ my @params;
+ my $query = "
SELECT DISTINCT b.bug_id
FROM bugs b
INNER JOIN flags f ON f.bug_id = b.bug_id\n";
- if ($q->{start_date}) {
- $query .= "INNER JOIN bugs_activity a ON a.bug_id = b.bug_id\n";
- }
+ if ($q->{start_date}) {
+ $query .= "INNER JOIN bugs_activity a ON a.bug_id = b.bug_id\n";
+ }
- $query .= "WHERE ";
+ $query .= "WHERE ";
- if ($q->{start_date}) {
- push @where, "(a.fieldid = ?)";
- push @params, $q->{field_id};
+ if ($q->{start_date}) {
+ push @where, "(a.fieldid = ?)";
+ push @params, $q->{field_id};
- push @where, "(CONVERT_TZ(a.bug_when, 'UTC', 'America/Los_Angeles') >= ?)";
- push @params, $q->{start_date} . ' 00:00:00';
- push @where, "(CONVERT_TZ(a.bug_when, 'UTC', 'America/Los_Angeles') <= ?)";
- push @params, $q->{end_date} . ' 23:59:59';
+ push @where, "(CONVERT_TZ(a.bug_when, 'UTC', 'America/Los_Angeles') >= ?)";
+ push @params, $q->{start_date} . ' 00:00:00';
+ push @where, "(CONVERT_TZ(a.bug_when, 'UTC', 'America/Los_Angeles') <= ?)";
+ push @params, $q->{end_date} . ' 23:59:59';
- push @where, "(a.added LIKE ?)";
- push @params, '%' . $q->{flag_name} . $q->{flag_status} . '%';
- }
+ push @where, "(a.added LIKE ?)";
+ push @params, '%' . $q->{flag_name} . $q->{flag_status} . '%';
+ }
- my ($type_id) = $dbh->selectrow_array(
- "SELECT id FROM flagtypes WHERE name = ?",
- undef,
- $q->{flag_name}
- );
- push @where, "(f.type_id = ?)";
- push @params, $type_id;
+ my ($type_id) = $dbh->selectrow_array("SELECT id FROM flagtypes WHERE name = ?",
+ undef, $q->{flag_name});
+ push @where, "(f.type_id = ?)";
+ push @params, $type_id;
- push @where, "(f.status = ?)";
- push @params, $q->{flag_status};
+ push @where, "(f.status = ?)";
+ push @params, $q->{flag_status};
- if ($q->{product_id}) {
- push @where, "(b.product_id = ?)";
- push @params, $q->{product_id};
- }
+ if ($q->{product_id}) {
+ push @where, "(b.product_id = ?)";
+ push @params, $q->{product_id};
+ }
- if (scalar @{$q->{fields}}) {
- my @fields;
- foreach my $field (@{$q->{fields}}) {
- my $field_sql = "(";
- if ($field->{type} == FIELD_TYPE_EXTENSION) {
- $field_sql .= "
+ if (scalar @{$q->{fields}}) {
+ my @fields;
+ foreach my $field (@{$q->{fields}}) {
+ my $field_sql = "(";
+ if ($field->{type} == FIELD_TYPE_EXTENSION) {
+ $field_sql .= "
COALESCE(
(SELECT tracking_flags_bugs.value
FROM tracking_flags_bugs
LEFT JOIN tracking_flags
ON tracking_flags.id = tracking_flags_bugs.tracking_flag_id
WHERE tracking_flags_bugs.bug_id = b.bug_id
- AND tracking_flags.name = " . $dbh->quote($field->{name}) . ")
+ AND tracking_flags.name = "
+ . $dbh->quote($field->{name}) . ")
, '') ";
- }
- else {
- $field_sql .= "b." . $field->{name};
- }
- $field_sql .= " " . ($field->{value} eq '+' ? '' : 'NOT ') . "IN ('fixed','verified'))";
- push(@fields, $field_sql);
- }
- my $join = uc $q->{join};
- push @where, '(' . join(" $join ", @fields) . ')';
}
-
- $query .= join("\nAND ", @where);
-
- my $bugs = $dbh->selectcol_arrayref($query, undef, @params);
- push @$bugs, 0 unless @$bugs;
-
- my $urlbase = Bugzilla->localconfig->{urlbase};
- my $cgi = Bugzilla->cgi;
- print $cgi->redirect(
- -url => "${urlbase}buglist.cgi?bug_id=" . join(',', @$bugs)
- );
- exit;
+ else {
+ $field_sql .= "b." . $field->{name};
+ }
+ $field_sql
+ .= " " . ($field->{value} eq '+' ? '' : 'NOT ') . "IN ('fixed','verified'))";
+ push(@fields, $field_sql);
+ }
+ my $join = uc $q->{join};
+ push @where, '(' . join(" $join ", @fields) . ')';
}
- #
- # set template vars
- #
-
- my $json = JSON->new()->shrink(1);
- $vars->{flags_json} = $json->encode(\@flags_json);
- $vars->{products_json} = $json->encode(\@products_json);
- $vars->{fields_json} = $json->encode(\@fields_json);
- $vars->{flag_names} = \@flag_names;
- $vars->{ranges} = DATE_RANGES;
- $vars->{default_query} = $input->{q};
- $vars->{is_custom} = $input->{is_custom};
- foreach my $field (qw(product flags range)) {
- $vars->{$field} = $input->{$field};
- }
+ $query .= join("\nAND ", @where);
+
+ my $bugs = $dbh->selectcol_arrayref($query, undef, @params);
+ push @$bugs, 0 unless @$bugs;
+
+ my $urlbase = Bugzilla->localconfig->{urlbase};
+ my $cgi = Bugzilla->cgi;
+ print $cgi->redirect(
+ -url => "${urlbase}buglist.cgi?bug_id=" . join(',', @$bugs));
+ exit;
+ }
+
+ #
+ # set template vars
+ #
+
+ my $json = JSON->new()->shrink(1);
+ $vars->{flags_json} = $json->encode(\@flags_json);
+ $vars->{products_json} = $json->encode(\@products_json);
+ $vars->{fields_json} = $json->encode(\@fields_json);
+ $vars->{flag_names} = \@flag_names;
+ $vars->{ranges} = DATE_RANGES;
+ $vars->{default_query} = $input->{q};
+ $vars->{is_custom} = $input->{is_custom};
+ foreach my $field (qw(product flags range)) {
+ $vars->{$field} = $input->{$field};
+ }
}
sub _parse_query {
- my $q = shift;
- my @query = split(/:/, $q);
- my $query;
-
- # field_id for flag changes
- $query->{field_id} = get_field_id('flagtypes.name');
-
- # flag_name
- my $flag_name = shift @query;
- @{Bugzilla::FlagType::match({ name => $flag_name, is_active => 1 })}
- or ThrowUserError('report_invalid_parameter', { name => 'flag_name' });
- trick_taint($flag_name);
- $query->{flag_name} = $flag_name;
-
- # flag_status
- my $flag_status = shift @query;
- $flag_status =~ /^([\?\-\+])$/
- or ThrowUserError('report_invalid_parameter', { name => 'flag_status' });
- $query->{flag_status} = $1;
-
- # date_range -> from_ymd to_ymd
- my $date_range = shift @query;
- if ($date_range ne '*') {
- $date_range =~ /^(\d\d\d\d)(\d\d)(\d\d)-(\d\d\d\d)(\d\d)(\d\d)$/
- or ThrowUserError('report_invalid_parameter', { name => 'date_range' });
- $query->{start_date} = "$1-$2-$3";
- $query->{end_date} = "$4-$5-$6";
- validate_date($query->{start_date})
- || ThrowUserError('illegal_date', { date => $query->{start_date},
- format => 'YYYY-MM-DD' });
- validate_date($query->{end_date})
- || ThrowUserError('illegal_date', { date => $query->{end_date},
- format => 'YYYY-MM-DD' });
- }
-
- # product_id
- my $product_id = shift @query;
- $product_id =~ /^(\d+)$/
- or ThrowUserError('report_invalid_parameter', { name => 'product_id' });
- $query->{product_id} = $1;
-
- # join
- my $join = shift @query;
- $join =~ /^(and|or)$/
- or ThrowUserError('report_invalid_parameter', { name => 'join' });
- $query->{join} = $1;
-
- # fields
- my @fields;
- foreach my $field (@query) {
- $field =~ /^(\d+)([\-\+])$/
- or ThrowUserError('report_invalid_parameter', { name => 'fields' });
- my ($id, $value) = ($1, $2);
- my $field_obj = Bugzilla::Field->new($id)
- or ThrowUserError('report_invalid_parameter', { name => 'field_id' });
- push @fields, { id => $id, value => $value,
- name => $field_obj->name, type => $field_obj->type };
- }
- $query->{fields} = \@fields;
-
- return $query;
+ my $q = shift;
+ my @query = split(/:/, $q);
+ my $query;
+
+ # field_id for flag changes
+ $query->{field_id} = get_field_id('flagtypes.name');
+
+ # flag_name
+ my $flag_name = shift @query;
+ @{Bugzilla::FlagType::match({name => $flag_name, is_active => 1})}
+ or ThrowUserError('report_invalid_parameter', {name => 'flag_name'});
+ trick_taint($flag_name);
+ $query->{flag_name} = $flag_name;
+
+ # flag_status
+ my $flag_status = shift @query;
+ $flag_status =~ /^([\?\-\+])$/
+ or ThrowUserError('report_invalid_parameter', {name => 'flag_status'});
+ $query->{flag_status} = $1;
+
+ # date_range -> from_ymd to_ymd
+ my $date_range = shift @query;
+ if ($date_range ne '*') {
+ $date_range =~ /^(\d\d\d\d)(\d\d)(\d\d)-(\d\d\d\d)(\d\d)(\d\d)$/
+ or ThrowUserError('report_invalid_parameter', {name => 'date_range'});
+ $query->{start_date} = "$1-$2-$3";
+ $query->{end_date} = "$4-$5-$6";
+ validate_date($query->{start_date})
+ || ThrowUserError('illegal_date',
+ {date => $query->{start_date}, format => 'YYYY-MM-DD'});
+ validate_date($query->{end_date})
+ || ThrowUserError('illegal_date',
+ {date => $query->{end_date}, format => 'YYYY-MM-DD'});
+ }
+
+ # product_id
+ my $product_id = shift @query;
+ $product_id =~ /^(\d+)$/
+ or ThrowUserError('report_invalid_parameter', {name => 'product_id'});
+ $query->{product_id} = $1;
+
+ # join
+ my $join = shift @query;
+ $join =~ /^(and|or)$/
+ or ThrowUserError('report_invalid_parameter', {name => 'join'});
+ $query->{join} = $1;
+
+ # fields
+ my @fields;
+ foreach my $field (@query) {
+ $field =~ /^(\d+)([\-\+])$/
+ or ThrowUserError('report_invalid_parameter', {name => 'fields'});
+ my ($id, $value) = ($1, $2);
+ my $field_obj = Bugzilla::Field->new($id)
+ or ThrowUserError('report_invalid_parameter', {name => 'field_id'});
+ push @fields,
+ {
+ id => $id,
+ value => $value,
+ name => $field_obj->name,
+ type => $field_obj->type
+ };
+ }
+ $query->{fields} = \@fields;
+
+ return $query;
}
1;
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;
diff --git a/extensions/BMO/lib/Reports/UserActivity.pm b/extensions/BMO/lib/Reports/UserActivity.pm
index 8dfe0c5cd..3be6f74c9 100644
--- a/extensions/BMO/lib/Reports/UserActivity.pm
+++ b/extensions/BMO/lib/Reports/UserActivity.pm
@@ -18,104 +18,104 @@ use Bugzilla::Util qw(trim);
use DateTime;
sub report {
- my ($vars) = @_;
- my $dbh = Bugzilla->dbh;
- my $input = Bugzilla->input_params;
-
- my @who = ();
- my $from = trim($input->{'from'} || '');
- my $to = trim($input->{'to'} || '');
- my $action = $input->{'action'} || '';
-
- # fix non-breaking hyphens
- $from =~ s/\N{U+2011}/-/g;
- $to =~ s/\N{U+2011}/-/g;
-
- if ($from eq '') {
- my $dt = DateTime->now()->subtract('weeks' => 1);
- $from = $dt->ymd('-');
+ my ($vars) = @_;
+ my $dbh = Bugzilla->dbh;
+ my $input = Bugzilla->input_params;
+
+ my @who = ();
+ my $from = trim($input->{'from'} || '');
+ my $to = trim($input->{'to'} || '');
+ my $action = $input->{'action'} || '';
+
+ # fix non-breaking hyphens
+ $from =~ s/\N{U+2011}/-/g;
+ $to =~ s/\N{U+2011}/-/g;
+
+ if ($from eq '') {
+ my $dt = DateTime->now()->subtract('weeks' => 1);
+ $from = $dt->ymd('-');
+ }
+ if ($to eq '') {
+ my $dt = DateTime->now();
+ $to = $dt->ymd('-');
+ }
+
+ if ($action eq 'run') {
+ if (!exists $input->{'who'} || $input->{'who'} eq '') {
+ ThrowUserError('user_activity_missing_username');
}
- if ($to eq '') {
- my $dt = DateTime->now();
- $to = $dt->ymd('-');
- }
-
- if ($action eq 'run') {
- if (!exists $input->{'who'} || $input->{'who'} eq '') {
- ThrowUserError('user_activity_missing_username');
- }
- Bugzilla::User::match_field({ 'who' => {'type' => 'multi'} });
+ Bugzilla::User::match_field({'who' => {'type' => 'multi'}});
- my $from_dt = string_to_datetime($from);
- $from = $from_dt->ymd();
+ my $from_dt = string_to_datetime($from);
+ $from = $from_dt->ymd();
- my $to_dt = string_to_datetime($to);
- $to = $to_dt->ymd();
+ my $to_dt = string_to_datetime($to);
+ $to = $to_dt->ymd();
- my ($activity_joins, $activity_where) = ('', '');
- my ($attachments_joins, $attachments_where) = ('', '');
- my ($tags_activity_joins, $tags_activity_where) = ('', '');
- if (Bugzilla->params->{"insidergroup"}
- && !Bugzilla->user->in_group(Bugzilla->params->{'insidergroup'}))
- {
- $activity_joins = "LEFT JOIN attachments
+ my ($activity_joins, $activity_where) = ('', '');
+ my ($attachments_joins, $attachments_where) = ('', '');
+ my ($tags_activity_joins, $tags_activity_where) = ('', '');
+ if (Bugzilla->params->{"insidergroup"}
+ && !Bugzilla->user->in_group(Bugzilla->params->{'insidergroup'}))
+ {
+ $activity_joins = "LEFT JOIN attachments
ON attachments.attach_id = bugs_activity.attach_id";
- $activity_where = "AND COALESCE(attachments.isprivate, 0) = 0";
- $attachments_where = $activity_where;
+ $activity_where = "AND COALESCE(attachments.isprivate, 0) = 0";
+ $attachments_where = $activity_where;
- $tags_activity_joins = 'LEFT JOIN longdescs
+ $tags_activity_joins = 'LEFT JOIN longdescs
ON longdescs_tags_activity.comment_id = longdescs.comment_id';
- $tags_activity_where = 'AND COALESCE(longdescs.isprivate, 0) = 0';
- }
+ $tags_activity_where = 'AND COALESCE(longdescs.isprivate, 0) = 0';
+ }
- my @who_bits;
- foreach my $who (
- ref $input->{'who'}
- ? @{$input->{'who'}}
- : $input->{'who'}
- ) {
- push @who, $who;
- push @who_bits, '?';
- }
- my $who_bits = join(',', @who_bits);
-
- if (!@who) {
- my $template = Bugzilla->template;
- my $cgi = Bugzilla->cgi;
- my $vars = {};
- $vars->{'script'} = $cgi->url(-relative => 1);
- $vars->{'fields'} = {};
- $vars->{'matches'} = [];
- $vars->{'matchsuccess'} = 0;
- $vars->{'matchmultiple'} = 1;
- print $cgi->header();
- $template->process("global/confirm-user-match.html.tmpl", $vars)
- || ThrowTemplateError($template->error());
- exit;
- }
+ my @who_bits;
+ foreach my $who (ref $input->{'who'} ? @{$input->{'who'}} : $input->{'who'}) {
+ push @who, $who;
+ push @who_bits, '?';
+ }
+ my $who_bits = join(',', @who_bits);
+
+ if (!@who) {
+ my $template = Bugzilla->template;
+ my $cgi = Bugzilla->cgi;
+ my $vars = {};
+ $vars->{'script'} = $cgi->url(-relative => 1);
+ $vars->{'fields'} = {};
+ $vars->{'matches'} = [];
+ $vars->{'matchsuccess'} = 0;
+ $vars->{'matchmultiple'} = 1;
+ print $cgi->header();
+ $template->process("global/confirm-user-match.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+ exit;
+ }
- $from_dt = $from_dt->ymd() . ' 00:00:00';
- $to_dt = $to_dt->ymd() . ' 23:59:59';
- my @params;
- for (1..5) {
- push @params, @who;
- push @params, ($from_dt, $to_dt);
- }
+ $from_dt = $from_dt->ymd() . ' 00:00:00';
+ $to_dt = $to_dt->ymd() . ' 23:59:59';
+ my @params;
+ for (1 .. 5) {
+ push @params, @who;
+ push @params, ($from_dt, $to_dt);
+ }
- my $order = ($input->{'group'} && $input->{'group'} eq 'bug')
- ? 'bug_id, bug_when' : 'bug_when';
+ my $order
+ = ($input->{'group'} && $input->{'group'} eq 'bug')
+ ? 'bug_id, bug_when'
+ : 'bug_when';
- my $comment_filter = '';
- if (!Bugzilla->user->is_insider) {
- $comment_filter = 'AND longdescs.isprivate = 0';
- }
+ my $comment_filter = '';
+ if (!Bugzilla->user->is_insider) {
+ $comment_filter = 'AND longdescs.isprivate = 0';
+ }
- my $query = "
+ my $query = "
SELECT
fielddefs.name,
bugs_activity.bug_id,
bugs_activity.attach_id,
- ".$dbh->sql_date_format('bugs_activity.bug_when', '%Y.%m.%d %H:%i:%s')." AS ts,
+ "
+ . $dbh->sql_date_format('bugs_activity.bug_when', '%Y.%m.%d %H:%i:%s')
+ . " AS ts,
bugs_activity.removed,
bugs_activity.added,
profiles.login_name,
@@ -138,8 +138,10 @@ sub report {
'comment_tag' AS name,
longdescs_tags_activity.bug_id,
NULL as attach_id,
- ".$dbh->sql_date_format('longdescs_tags_activity.bug_when',
- '%Y.%m.%d %H:%i:%s') . " AS bug_when,
+ "
+ . $dbh->sql_date_format('longdescs_tags_activity.bug_when',
+ '%Y.%m.%d %H:%i:%s')
+ . " AS bug_when,
longdescs_tags_activity.removed,
longdescs_tags_activity.added,
profiles.login_name,
@@ -160,7 +162,8 @@ sub report {
'bug_id' AS name,
bugs.bug_id,
NULL AS attach_id,
- ".$dbh->sql_date_format('bugs.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts,
+ "
+ . $dbh->sql_date_format('bugs.creation_ts', '%Y.%m.%d %H:%i:%s') . " AS ts,
'(new bug)' AS removed,
bugs.short_desc AS added,
profiles.login_name,
@@ -199,7 +202,9 @@ sub report {
'attachments.description' AS name,
attachments.bug_id,
attachments.attach_id,
- ".$dbh->sql_date_format('attachments.creation_ts', '%Y.%m.%d %H:%i:%s')." AS ts,
+ "
+ . $dbh->sql_date_format('attachments.creation_ts', '%Y.%m.%d %H:%i:%s')
+ . " AS ts,
'(new attachment)' AS removed,
attachments.description AS added,
profiles.login_name,
@@ -215,119 +220,118 @@ sub report {
ORDER BY $order ";
- my $list = $dbh->selectall_arrayref($query, undef, @params);
+ my $list = $dbh->selectall_arrayref($query, undef, @params);
- if ($input->{debug}) {
- while (my $param = shift @params) {
- $query =~ s/\?/$dbh->quote($param)/e;
- }
- $vars->{debug_sql} = $query;
+ if ($input->{debug}) {
+ while (my $param = shift @params) {
+ $query =~ s/\?/$dbh->quote($param)/e;
+ }
+ $vars->{debug_sql} = $query;
+ }
+
+ my @operations;
+ my $operation = {};
+ my $changes = [];
+ my $incomplete_data = 0;
+ my %bug_ids;
+
+ foreach my $entry (@$list) {
+ my ($fieldname, $bugid, $attachid, $when, $removed, $added, $who, $comment_id)
+ = @$entry;
+ my %change;
+ my $activity_visible = 1;
+
+ next unless Bugzilla->user->can_see_bug($bugid);
+
+ # check if the user should see this field's activity
+ if ( $fieldname eq 'remaining_time'
+ || $fieldname eq 'estimated_time'
+ || $fieldname eq 'work_time'
+ || $fieldname eq 'deadline')
+ {
+ $activity_visible = Bugzilla->user->is_timetracker;
+ }
+ elsif ($fieldname eq 'longdescs.isprivate'
+ && !Bugzilla->user->is_insider
+ && $added)
+ {
+ $activity_visible = 0;
+ }
+ else {
+ $activity_visible = 1;
+ }
+
+ if ($activity_visible) {
+
+ # Check for the results of an old Bugzilla data corruption bug
+ if ( ($added eq '?' && $removed eq '?')
+ || ($added =~ /^\? / || $removed =~ /^\? /))
+ {
+ $incomplete_data = 1;
}
- my @operations;
- my $operation = {};
- my $changes = [];
- my $incomplete_data = 0;
- my %bug_ids;
-
- foreach my $entry (@$list) {
- my ($fieldname, $bugid, $attachid, $when, $removed, $added, $who,
- $comment_id) = @$entry;
- my %change;
- my $activity_visible = 1;
-
- next unless Bugzilla->user->can_see_bug($bugid);
-
- # check if the user should see this field's activity
- if ($fieldname eq 'remaining_time'
- || $fieldname eq 'estimated_time'
- || $fieldname eq 'work_time'
- || $fieldname eq 'deadline')
- {
- $activity_visible = Bugzilla->user->is_timetracker;
- }
- elsif ($fieldname eq 'longdescs.isprivate'
- && !Bugzilla->user->is_insider
- && $added)
- {
- $activity_visible = 0;
- }
- else {
- $activity_visible = 1;
- }
-
- if ($activity_visible) {
- # Check for the results of an old Bugzilla data corruption bug
- if (($added eq '?' && $removed eq '?')
- || ($added =~ /^\? / || $removed =~ /^\? /)) {
- $incomplete_data = 1;
- }
-
- # Start a new changeset if required (depends on the grouping type)
- my $is_new_changeset;
- if ($order eq 'bug_when') {
- $is_new_changeset =
- $operation->{'who'} &&
- (
- $who ne $operation->{'who'}
- || $when ne $operation->{'when'}
- || $bugid != $operation->{'bug'}
- );
- } else {
- $is_new_changeset =
- $operation->{'bug'} &&
- $bugid != $operation->{'bug'};
- }
- if ($is_new_changeset) {
- $operation->{'changes'} = $changes;
- push (@operations, $operation);
- $operation = {};
- $changes = [];
- }
-
- $bug_ids{$bugid} = 1;
-
- $operation->{'bug'} = $bugid;
- $operation->{'who'} = $who;
- $operation->{'when'} = $when;
-
- $change{'fieldname'} = $fieldname;
- $change{'attachid'} = $attachid;
- $change{'removed'} = $removed;
- $change{'added'} = $added;
- $change{'when'} = $when;
-
- if ($comment_id) {
- $change{'comment'} = Bugzilla::Comment->new($comment_id);
- next if $change{'comment'}->count == 0;
- }
-
- if ($attachid) {
- $change{'attach'} = Bugzilla::Attachment->new($attachid);
- }
-
- push (@$changes, \%change);
- }
+ # Start a new changeset if required (depends on the grouping type)
+ my $is_new_changeset;
+ if ($order eq 'bug_when') {
+ $is_new_changeset
+ = $operation->{'who'}
+ && ($who ne $operation->{'who'}
+ || $when ne $operation->{'when'}
+ || $bugid != $operation->{'bug'});
+ }
+ else {
+ $is_new_changeset = $operation->{'bug'} && $bugid != $operation->{'bug'};
}
+ if ($is_new_changeset) {
+ $operation->{'changes'} = $changes;
+ push(@operations, $operation);
+ $operation = {};
+ $changes = [];
+ }
+
+ $bug_ids{$bugid} = 1;
+
+ $operation->{'bug'} = $bugid;
+ $operation->{'who'} = $who;
+ $operation->{'when'} = $when;
- if ($operation->{'who'}) {
- $operation->{'changes'} = $changes;
- push (@operations, $operation);
+ $change{'fieldname'} = $fieldname;
+ $change{'attachid'} = $attachid;
+ $change{'removed'} = $removed;
+ $change{'added'} = $added;
+ $change{'when'} = $when;
+
+ if ($comment_id) {
+ $change{'comment'} = Bugzilla::Comment->new($comment_id);
+ next if $change{'comment'}->count == 0;
+ }
+
+ if ($attachid) {
+ $change{'attach'} = Bugzilla::Attachment->new($attachid);
}
- $vars->{'incomplete_data'} = $incomplete_data;
- $vars->{'operations'} = \@operations;
+ push(@$changes, \%change);
+ }
+ }
- my @bug_ids = sort { $a <=> $b } keys %bug_ids;
- $vars->{'bug_ids'} = \@bug_ids;
+ if ($operation->{'who'}) {
+ $operation->{'changes'} = $changes;
+ push(@operations, $operation);
}
- $vars->{'action'} = $action;
- $vars->{'who'} = join(',', @who);
- $vars->{'who_count'} = scalar @who;
- $vars->{'from'} = $from;
- $vars->{'to'} = $to;
- $vars->{'group'} = $input->{'group'};
+ $vars->{'incomplete_data'} = $incomplete_data;
+ $vars->{'operations'} = \@operations;
+
+ my @bug_ids = sort { $a <=> $b } keys %bug_ids;
+ $vars->{'bug_ids'} = \@bug_ids;
+ }
+
+ $vars->{'action'} = $action;
+ $vars->{'who'} = join(',', @who);
+ $vars->{'who_count'} = scalar @who;
+ $vars->{'from'} = $from;
+ $vars->{'to'} = $to;
+ $vars->{'group'} = $input->{'group'};
}
1;