summaryrefslogtreecommitdiffstats
path: root/extensions/BugmailFilter
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/BugmailFilter')
-rw-r--r--extensions/BugmailFilter/Config.pm2
-rw-r--r--extensions/BugmailFilter/Extension.pm807
-rw-r--r--extensions/BugmailFilter/lib/Constants.pm120
-rw-r--r--extensions/BugmailFilter/lib/FakeField.pm50
-rw-r--r--extensions/BugmailFilter/lib/Filter.pm217
5 files changed, 551 insertions, 645 deletions
diff --git a/extensions/BugmailFilter/Config.pm b/extensions/BugmailFilter/Config.pm
index 5948c3b64..5b9585cee 100644
--- a/extensions/BugmailFilter/Config.pm
+++ b/extensions/BugmailFilter/Config.pm
@@ -11,7 +11,7 @@ use 5.10.1;
use strict;
use warnings;
-use constant NAME => 'BugmailFilter';
+use constant NAME => 'BugmailFilter';
use constant REQUIRED_MODULES => [];
use constant OPTIONAL_MODULES => [];
diff --git a/extensions/BugmailFilter/Extension.pm b/extensions/BugmailFilter/Extension.pm
index d4d7bb790..063cb273d 100644
--- a/extensions/BugmailFilter/Extension.pm
+++ b/extensions/BugmailFilter/Extension.pm
@@ -34,185 +34,172 @@ use Sys::Syslog qw(:DEFAULT);
#
sub user_preferences {
- my ($self, $args) = @_;
- return unless $args->{current_tab} eq 'bugmail_filter';
-
- if ($args->{save_changes}) {
- my $input = Bugzilla->input_params;
-
- if ($input->{add_filter}) {
-
- # add a new filter
-
- my $params = {
- user_id => Bugzilla->user->id,
- };
- $params->{field_name} = $input->{field} || IS_NULL;
- if ($params->{field_name} eq '~') {
- $params->{field_name} = '~' . $input->{field_contains};
- }
- $params->{relationship} = $input->{relationship} || IS_NULL;
- if ($input->{changer}) {
- Bugzilla::User::match_field({ changer => { type => 'single'} });
- $params->{changer_id} = Bugzilla::User->check({
- name => $input->{changer},
- cache => 1,
- })->id;
- }
- else {
- $params->{changer_id} = IS_NULL;
- }
- if (my $product_name = $input->{product}) {
- my $product = Bugzilla::Product->check({
- name => $product_name, cache => 1
- });
- $params->{product_id} = $product->id;
-
- if (my $component_name = $input->{component}) {
- $params->{component_id} = Bugzilla::Component->check({
- name => $component_name, product => $product,
- cache => 1
- })->id;
- }
- else {
- $params->{component_id} = IS_NULL;
- }
- }
- else {
- $params->{product_id} = IS_NULL;
- $params->{component_id} = IS_NULL;
- }
-
- if (@{ Bugzilla::Extension::BugmailFilter::Filter->match($params) }) {
- ThrowUserError('bugmail_filter_exists');
- }
- $params->{action} = $input->{action} eq 'Exclude' ? 1 : 0;
- foreach my $name (keys %$params) {
- $params->{$name} = undef
- if $params->{$name} eq IS_NULL;
- }
- Bugzilla::Extension::BugmailFilter::Filter->create($params);
+ my ($self, $args) = @_;
+ return unless $args->{current_tab} eq 'bugmail_filter';
+
+ if ($args->{save_changes}) {
+ my $input = Bugzilla->input_params;
+
+ if ($input->{add_filter}) {
+
+ # add a new filter
+
+ my $params = {user_id => Bugzilla->user->id,};
+ $params->{field_name} = $input->{field} || IS_NULL;
+ if ($params->{field_name} eq '~') {
+ $params->{field_name} = '~' . $input->{field_contains};
+ }
+ $params->{relationship} = $input->{relationship} || IS_NULL;
+ if ($input->{changer}) {
+ Bugzilla::User::match_field({changer => {type => 'single'}});
+ $params->{changer_id}
+ = Bugzilla::User->check({name => $input->{changer}, cache => 1,})->id;
+ }
+ else {
+ $params->{changer_id} = IS_NULL;
+ }
+ if (my $product_name = $input->{product}) {
+ my $product = Bugzilla::Product->check({name => $product_name, cache => 1});
+ $params->{product_id} = $product->id;
+
+ if (my $component_name = $input->{component}) {
+ $params->{component_id}
+ = Bugzilla::Component->check({
+ name => $component_name, product => $product, cache => 1
+ })->id;
}
-
- elsif ($input->{remove_filter}) {
-
- # remove filter(s)
-
- my $ids = ref($input->{remove}) ? $input->{remove} : [ $input->{remove} ];
- my $dbh = Bugzilla->dbh;
- my $user = Bugzilla->user;
-
- my $filters = Bugzilla::Extension::BugmailFilter::Filter->match({ id => $ids, user_id => $user->id });
- $dbh->bz_start_transaction;
- foreach my $filter (@$filters) {
- $filter->remove_from_db();
- }
- $dbh->bz_commit_transaction;
+ else {
+ $params->{component_id} = IS_NULL;
}
+ }
+ else {
+ $params->{product_id} = IS_NULL;
+ $params->{component_id} = IS_NULL;
+ }
+
+ if (@{Bugzilla::Extension::BugmailFilter::Filter->match($params)}) {
+ ThrowUserError('bugmail_filter_exists');
+ }
+ $params->{action} = $input->{action} eq 'Exclude' ? 1 : 0;
+ foreach my $name (keys %$params) {
+ $params->{$name} = undef if $params->{$name} eq IS_NULL;
+ }
+ Bugzilla::Extension::BugmailFilter::Filter->create($params);
}
- my $vars = $args->{vars};
- my $field_descs = template_var('field_descs');
+ elsif ($input->{remove_filter}) {
- # load all fields into a hash for easy manipulation
- my %fields =
- map { $_->name => $field_descs->{$_->name} }
- @{ Bugzilla->fields({ obsolete => 0 }) };
+ # remove filter(s)
- # remove time trackinger fields
- if (!Bugzilla->user->is_timetracker) {
- foreach my $field (TIMETRACKING_FIELDS) {
- delete $fields{$field};
- }
- }
+ my $ids = ref($input->{remove}) ? $input->{remove} : [$input->{remove}];
+ my $dbh = Bugzilla->dbh;
+ my $user = Bugzilla->user;
- # remove fields which don't make any sense to filter on
- foreach my $field (IGNORE_FIELDS) {
- delete $fields{$field};
+ my $filters = Bugzilla::Extension::BugmailFilter::Filter->match(
+ {id => $ids, user_id => $user->id});
+ $dbh->bz_start_transaction;
+ foreach my $filter (@$filters) {
+ $filter->remove_from_db();
+ }
+ $dbh->bz_commit_transaction;
}
+ }
- # remove all tracking flag fields. these change too frequently to be of
- # value, so they only add noise to the list.
- foreach my $field (Bugzilla->tracking_flag_names) {
- delete $fields{$field};
- }
+ my $vars = $args->{vars};
+ my $field_descs = template_var('field_descs');
- # add tracking flag types instead
- foreach my $field (
- @{ Bugzilla::Extension::BugmailFilter::FakeField->tracking_flag_fields() }
- ) {
- $fields{$field->name} = $field->description;
- }
+ # load all fields into a hash for easy manipulation
+ my %fields = map { $_->name => $field_descs->{$_->name} }
+ @{Bugzilla->fields({obsolete => 0})};
- # adjust the description for selected fields
- foreach my $field (keys %{ FIELD_DESCRIPTION_OVERRIDE() }) {
- $fields{$field} = FIELD_DESCRIPTION_OVERRIDE->{$field};
+ # remove time trackinger fields
+ if (!Bugzilla->user->is_timetracker) {
+ foreach my $field (TIMETRACKING_FIELDS) {
+ delete $fields{$field};
}
-
- # some fields are present in the changed-fields x-header but are not real
- # bugzilla fields
- foreach my $field (
- @{ Bugzilla::Extension::BugmailFilter::FakeField->fake_fields() }
- ) {
- $fields{$field->name} = $field->description;
+ }
+
+ # remove fields which don't make any sense to filter on
+ foreach my $field (IGNORE_FIELDS) {
+ delete $fields{$field};
+ }
+
+ # remove all tracking flag fields. these change too frequently to be of
+ # value, so they only add noise to the list.
+ foreach my $field (Bugzilla->tracking_flag_names) {
+ delete $fields{$field};
+ }
+
+ # add tracking flag types instead
+ foreach my $field (
+ @{Bugzilla::Extension::BugmailFilter::FakeField->tracking_flag_fields()})
+ {
+ $fields{$field->name} = $field->description;
+ }
+
+ # adjust the description for selected fields
+ foreach my $field (keys %{FIELD_DESCRIPTION_OVERRIDE()}) {
+ $fields{$field} = FIELD_DESCRIPTION_OVERRIDE->{$field};
+ }
+
+ # some fields are present in the changed-fields x-header but are not real
+ # bugzilla fields
+ foreach
+ my $field (@{Bugzilla::Extension::BugmailFilter::FakeField->fake_fields()})
+ {
+ $fields{$field->name} = $field->description;
+ }
+
+ $vars->{fields} = \%fields;
+ $vars->{field_list} = [sort { lc($a->{description}) cmp lc($b->{description}) }
+ map { {name => $_, description => $fields{$_}} } keys %fields];
+
+ $vars->{relationships} = FILTER_RELATIONSHIPS();
+
+ $vars->{filters} = [
+ sort {
+ $a->product_name cmp $b->product_name
+ || $a->component_name cmp $b->component_name
+ || $a->field_name cmp $b->field_name
+ } @{Bugzilla::Extension::BugmailFilter::Filter->match({
+ user_id => Bugzilla->user->id,
+ })
}
+ ];
- $vars->{fields} = \%fields;
- $vars->{field_list} = [
- sort { lc($a->{description}) cmp lc($b->{description}) }
- map { { name => $_, description => $fields{$_} } }
- keys %fields
- ];
-
- $vars->{relationships} = FILTER_RELATIONSHIPS();
-
- $vars->{filters} = [
- sort {
- $a->product_name cmp $b->product_name
- || $a->component_name cmp $b->component_name
- || $a->field_name cmp $b->field_name
- }
- @{ Bugzilla::Extension::BugmailFilter::Filter->match({
- user_id => Bugzilla->user->id,
- }) }
- ];
-
- # set field_description
- foreach my $filter (@{ $vars->{filters} }) {
- my $field_name = $filter->field_name;
- if (!$field_name) {
- $filter->field_description('Any');
- }
- elsif (substr($field_name, 0, 1) eq '~') {
- $filter->field_description('~ ' . substr($field_name, 1));
- }
- else {
- $filter->field_description($fields{$field_name} || $filter->field->description);
- }
+ # set field_description
+ foreach my $filter (@{$vars->{filters}}) {
+ my $field_name = $filter->field_name;
+ if (!$field_name) {
+ $filter->field_description('Any');
}
-
- # build a list of tracking-flags, grouped by type
- require Bugzilla::Extension::TrackingFlags::Constants;
- require Bugzilla::Extension::TrackingFlags::Flag;
- my %flag_types =
- map { $_->{name} => $_->{description} }
- @{ Bugzilla::Extension::TrackingFlags::Constants::FLAG_TYPES() };
- my %tracking_flags_by_type;
- foreach my $flag (Bugzilla::Extension::TrackingFlags::Flag->get_all) {
- my $type = $flag_types{$flag->flag_type};
- $tracking_flags_by_type{$type} //= [];
- push @{ $tracking_flags_by_type{$type} }, $flag;
+ elsif (substr($field_name, 0, 1) eq '~') {
+ $filter->field_description('~ ' . substr($field_name, 1));
}
- my @tracking_flags_by_type;
- foreach my $type (sort keys %tracking_flags_by_type) {
- push @tracking_flags_by_type, {
- name => $type,
- flags => $tracking_flags_by_type{$type},
- };
+ else {
+ $filter->field_description($fields{$field_name} || $filter->field->description);
}
- $vars->{tracking_flags_by_type} = \@tracking_flags_by_type;
-
- ${ $args->{handled} } = 1;
+ }
+
+ # build a list of tracking-flags, grouped by type
+ require Bugzilla::Extension::TrackingFlags::Constants;
+ require Bugzilla::Extension::TrackingFlags::Flag;
+ my %flag_types = map { $_->{name} => $_->{description} }
+ @{Bugzilla::Extension::TrackingFlags::Constants::FLAG_TYPES()};
+ my %tracking_flags_by_type;
+ foreach my $flag (Bugzilla::Extension::TrackingFlags::Flag->get_all) {
+ my $type = $flag_types{$flag->flag_type};
+ $tracking_flags_by_type{$type} //= [];
+ push @{$tracking_flags_by_type{$type}}, $flag;
+ }
+ my @tracking_flags_by_type;
+ foreach my $type (sort keys %tracking_flags_by_type) {
+ push @tracking_flags_by_type,
+ {name => $type, flags => $tracking_flags_by_type{$type},};
+ }
+ $vars->{tracking_flags_by_type} = \@tracking_flags_by_type;
+
+ ${$args->{handled}} = 1;
}
#
@@ -220,219 +207,212 @@ sub user_preferences {
#
sub user_wants_mail {
- my ($self, $args) = @_;
- my ($user, $wants_mail, $diffs, $comments)
- = @$args{qw( user wants_mail fieldDiffs comments )};
-
- # already filtered by email prefs
- return unless $$wants_mail;
+ my ($self, $args) = @_;
+ my ($user, $wants_mail, $diffs, $comments)
+ = @$args{qw( user wants_mail fieldDiffs comments )};
+
+ # already filtered by email prefs
+ return unless $$wants_mail;
+
+ # avoid recursion
+ my $depth = 0;
+ for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
+ $depth++ if $sub eq 'Bugzilla::User::wants_bug_mail';
+ }
+ return if $depth > 1;
+
+ my $cache = Bugzilla->request_cache->{bugmail_filters} //= {};
+ my $filters = $cache->{$user->id}
+ //= Bugzilla::Extension::BugmailFilter::Filter->match({user_id => $user->id});
+ return unless @$filters;
+
+ my $fields = [
+ map { {
+ filter_field => $_->{field_name}, # filter's field_name
+ field_name => $_->{field_name}, # raw bugzilla field_name
+ } } grep {
+
+ # flags are added later
+ $_->{field_name} ne 'flagtypes.name'
+ } @$diffs
+ ];
+
+ # if more than one field was changed we need to check if the normal email
+ # preferences would have excluded the field.
+ if (@$fields > 1) {
+
+ # check each field individually and create filter objects if required
+ my @arg_list
+ = @$args{qw( bug relationship fieldDiffs comments dep_mail changer )};
+ foreach my $field (@$fields) {
- # avoid recursion
- my $depth = 0;
- for (my $stack = 1; my $sub = (caller($stack))[3]; $stack++) {
- $depth++ if $sub eq 'Bugzilla::User::wants_bug_mail';
- }
- return if $depth > 1;
-
- my $cache = Bugzilla->request_cache->{bugmail_filters} //= {};
- my $filters = $cache->{$user->id} //=
- Bugzilla::Extension::BugmailFilter::Filter->match({
- user_id => $user->id
- });
- return unless @$filters;
-
- my $fields = [
- map { {
- filter_field => $_->{field_name}, # filter's field_name
- field_name => $_->{field_name}, # raw bugzilla field_name
- } }
- grep {
- # flags are added later
- $_->{field_name} ne 'flagtypes.name'
- }
- @$diffs
- ];
-
- # if more than one field was changed we need to check if the normal email
- # preferences would have excluded the field.
- if (@$fields > 1) {
- # check each field individually and create filter objects if required
- my @arg_list = @$args{qw( bug relationship fieldDiffs comments dep_mail changer )};
- foreach my $field (@$fields) {
- # just a single diff
- foreach my $diff (@$diffs) {
- next unless $diff->{field_name} eq $field->{field_name};
- $arg_list[2] = [ $diff ];
- last;
- }
- if (!$user->wants_bug_mail(@arg_list)) {
- # changes to just this field would have been dropped by email
- # preferences. build a corresponding filter object so we
- # interact with email preferences correctly.
- push @$filters, Bugzilla::Extension::BugmailFilter::Filter->new_from_hash({
- field_name => $field->{field_name},
- action => 1,
- });
- }
- }
+ # just a single diff
+ foreach my $diff (@$diffs) {
+ next unless $diff->{field_name} eq $field->{field_name};
+ $arg_list[2] = [$diff];
+ last;
+ }
+ if (!$user->wants_bug_mail(@arg_list)) {
+
+ # changes to just this field would have been dropped by email
+ # preferences. build a corresponding filter object so we
+ # interact with email preferences correctly.
+ push @$filters,
+ Bugzilla::Extension::BugmailFilter::Filter->new_from_hash({
+ field_name => $field->{field_name}, action => 1,
+ });
+ }
}
+ }
- # insert fake fields for new attachments and comments
- if (@$comments) {
- if (grep { $_->type == CMT_ATTACHMENT_CREATED } @$comments) {
- push @$fields, { field_name => 'attachment.created',
- filter_field => 'attachment.created' };
- }
- if (grep { $_->type != CMT_ATTACHMENT_CREATED } @$comments) {
- push @$fields, { field_name => 'comment.created',
- filter_field => 'comment.created' };
- }
+ # insert fake fields for new attachments and comments
+ if (@$comments) {
+ if (grep { $_->type == CMT_ATTACHMENT_CREATED } @$comments) {
+ push @$fields,
+ {field_name => 'attachment.created', filter_field => 'attachment.created'};
}
-
- # insert fake fields for flags
- foreach my $diff (@$diffs) {
- next unless $diff->{field_name} eq 'flagtypes.name';
- foreach my $change (split(/, /, join(', ', ($diff->{old}, $diff->{new})))) {
- next unless $change =~ /^(.+)[\?\-+]/;
- push @$fields, {
- filter_field => $1,
- field_name => 'flagtypes.name',
- };
- }
+ if (grep { $_->type != CMT_ATTACHMENT_CREATED } @$comments) {
+ push @$fields,
+ {field_name => 'comment.created', filter_field => 'comment.created'};
}
-
- # set filter_field on tracking flags to tracking.$type
- require Bugzilla::Extension::TrackingFlags::Flag;
- my @tracking_flags = Bugzilla->tracking_flags;
- foreach my $field (@$fields) {
- next unless my $field_name = $field->{field_name};
- foreach my $tracking_flag (@tracking_flags) {
- if ($field_name eq $tracking_flag->name) {
- $field->{filter_field} = 'tracking.'. $tracking_flag->flag_type;
- }
- }
+ }
+
+ # insert fake fields for flags
+ foreach my $diff (@$diffs) {
+ next unless $diff->{field_name} eq 'flagtypes.name';
+ foreach my $change (split(/, /, join(', ', ($diff->{old}, $diff->{new})))) {
+ next unless $change =~ /^(.+)[\?\-+]/;
+ push @$fields, {filter_field => $1, field_name => 'flagtypes.name',};
}
-
- if (_should_drop($fields, $filters, $args)) {
- $$wants_mail = 0;
- openlog('apache', 'cons,pid', 'local4');
- syslog('notice', encode_utf8(sprintf(
- '[bugmail] %s (filtered) bug-%s %s',
- $args->{user}->login,
- $args->{bug}->id,
- $args->{bug}->short_desc,
- )));
- closelog();
+ }
+
+ # set filter_field on tracking flags to tracking.$type
+ require Bugzilla::Extension::TrackingFlags::Flag;
+ my @tracking_flags = Bugzilla->tracking_flags;
+ foreach my $field (@$fields) {
+ next unless my $field_name = $field->{field_name};
+ foreach my $tracking_flag (@tracking_flags) {
+ if ($field_name eq $tracking_flag->name) {
+ $field->{filter_field} = 'tracking.' . $tracking_flag->flag_type;
+ }
}
+ }
+
+ if (_should_drop($fields, $filters, $args)) {
+ $$wants_mail = 0;
+ openlog('apache', 'cons,pid', 'local4');
+ syslog(
+ 'notice',
+ encode_utf8(sprintf(
+ '[bugmail] %s (filtered) bug-%s %s',
+ $args->{user}->login,
+ $args->{bug}->id, $args->{bug}->short_desc,
+ ))
+ );
+ closelog();
+ }
}
sub _should_drop {
- my ($fields, $filters, $args) = @_;
-
- # calculate relationships
-
- my ($user, $bug, $relationship, $changer) = @$args{qw( user bug relationship changer )};
- my ($user_id, $login) = ($user->id, $user->login);
- my $bit_direct = Bugzilla::BugMail::BIT_DIRECT;
- my $bit_watching = Bugzilla::BugMail::BIT_WATCHING;
- my $bit_compwatch = 15; # from Bugzilla::Extension::ComponentWatching
-
- # the index of $rel_map corresponds to the values in FILTER_RELATIONSHIPS
- my @rel_map;
- $rel_map[1] = $bug->assigned_to->id == $user_id;
- $rel_map[2] = !$rel_map[1];
- $rel_map[3] = $bug->reporter->id == $user_id;
- $rel_map[4] = !$rel_map[3];
- if ($bug->qa_contact) {
- $rel_map[5] = $bug->qa_contact->id == $user_id;
- $rel_map[6] = !$rel_map[6];
+ my ($fields, $filters, $args) = @_;
+
+ # calculate relationships
+
+ my ($user, $bug, $relationship, $changer)
+ = @$args{qw( user bug relationship changer )};
+ my ($user_id, $login) = ($user->id, $user->login);
+ my $bit_direct = Bugzilla::BugMail::BIT_DIRECT;
+ my $bit_watching = Bugzilla::BugMail::BIT_WATCHING;
+ my $bit_compwatch = 15; # from Bugzilla::Extension::ComponentWatching
+
+ # the index of $rel_map corresponds to the values in FILTER_RELATIONSHIPS
+ my @rel_map;
+ $rel_map[1] = $bug->assigned_to->id == $user_id;
+ $rel_map[2] = !$rel_map[1];
+ $rel_map[3] = $bug->reporter->id == $user_id;
+ $rel_map[4] = !$rel_map[3];
+ if ($bug->qa_contact) {
+ $rel_map[5] = $bug->qa_contact->id == $user_id;
+ $rel_map[6] = !$rel_map[6];
+ }
+ $rel_map[7] = $bug->cc ? grep { $_ eq $login } @{$bug->cc} : 0;
+ $rel_map[8] = !$rel_map[8];
+ $rel_map[9] = ($relationship & $bit_watching or $relationship & $bit_compwatch);
+ $rel_map[10] = !$rel_map[9];
+ $rel_map[11] = $bug->is_mentor($user);
+ $rel_map[12] = !$rel_map[11];
+ foreach my $bool (@rel_map) {
+ $bool = $bool ? 1 : 0;
+ }
+
+ # exclusions
+ # drop email where we are excluding all changed fields
+
+ my $params = {
+ product_id => $bug->product_id,
+ component_id => $bug->component_id,
+ rel_map => \@rel_map,
+ changer_id => $changer->id,
+ };
+
+ foreach my $field (@$fields) {
+ $params->{field} = $field;
+ foreach my $filter (grep { $_->is_exclude } @$filters) {
+ if ($filter->matches($params)) {
+ $field->{exclude} = 1;
+ last;
+ }
}
- $rel_map[7] = $bug->cc
- ? grep { $_ eq $login } @{ $bug->cc }
- : 0;
- $rel_map[8] = !$rel_map[8];
- $rel_map[9] = (
- $relationship & $bit_watching
- or $relationship & $bit_compwatch
- );
- $rel_map[10] = !$rel_map[9];
- $rel_map[11] = $bug->is_mentor($user);
- $rel_map[12] = !$rel_map[11];
- foreach my $bool (@rel_map) {
- $bool = $bool ? 1 : 0;
- }
-
- # exclusions
- # drop email where we are excluding all changed fields
-
- my $params = {
- product_id => $bug->product_id,
- component_id => $bug->component_id,
- rel_map => \@rel_map,
- changer_id => $changer->id,
- };
-
- foreach my $field (@$fields) {
- $params->{field} = $field;
- foreach my $filter (grep { $_->is_exclude } @$filters) {
- if ($filter->matches($params)) {
- $field->{exclude} = 1;
- last;
- }
- }
+ }
+
+ # no need to process includes if nothing was excluded
+ if (!grep { $_->{exclude} } @$fields) {
+ return 0;
+ }
+
+ # inclusions
+ # flip the bit for fields that should be included
+
+ foreach my $field (@$fields) {
+ $params->{field} = $field;
+ foreach my $filter (grep { $_->is_include } @$filters) {
+ if ($filter->matches($params)) {
+ $field->{exclude} = 0;
+ last;
+ }
}
+ }
- # no need to process includes if nothing was excluded
- if (!grep { $_->{exclude} } @$fields) {
- return 0;
- }
-
- # inclusions
- # flip the bit for fields that should be included
-
- foreach my $field (@$fields) {
- $params->{field} = $field;
- foreach my $filter (grep { $_->is_include } @$filters) {
- if ($filter->matches($params)) {
- $field->{exclude} = 0;
- last;
- }
- }
- }
-
- # drop if all fields are still excluded
- return !(grep { !$_->{exclude} } @$fields);
+ # drop if all fields are still excluded
+ return !(grep { !$_->{exclude} } @$fields);
}
# catch when fields are renamed, and update the field_name entires
sub object_end_of_update {
- my ($self, $args) = @_;
- my $object = $args->{object};
+ my ($self, $args) = @_;
+ my $object = $args->{object};
- return unless $object->isa('Bugzilla::Field')
- || $object->isa('Bugzilla::Extension::TrackingFlags::Flag');
+ return
+ unless $object->isa('Bugzilla::Field')
+ || $object->isa('Bugzilla::Extension::TrackingFlags::Flag');
- return unless exists $args->{changes}->{name};
+ return unless exists $args->{changes}->{name};
- my $old_name = $args->{changes}->{name}->[0];
- my $new_name = $args->{changes}->{name}->[1];
+ my $old_name = $args->{changes}->{name}->[0];
+ my $new_name = $args->{changes}->{name}->[1];
- Bugzilla->dbh->do(
- "UPDATE bugmail_filters SET field_name=? WHERE field_name=?",
- undef,
- $new_name, $old_name);
+ Bugzilla->dbh->do("UPDATE bugmail_filters SET field_name=? WHERE field_name=?",
+ undef, $new_name, $old_name);
}
sub reorg_move_component {
- my ($self, $args) = @_;
- my $new_product = $args->{new_product};
- my $component = $args->{component};
-
- Bugzilla->dbh->do(
- "UPDATE bugmail_filters SET product_id=? WHERE component_id=?",
- undef,
- $new_product->id, $component->id,
- );
+ my ($self, $args) = @_;
+ my $new_product = $args->{new_product};
+ my $component = $args->{component};
+
+ Bugzilla->dbh->do(
+ "UPDATE bugmail_filters SET product_id=? WHERE component_id=?",
+ undef, $new_product->id, $component->id,);
}
#
@@ -440,92 +420,61 @@ sub reorg_move_component {
#
sub db_schema_abstract_schema {
- my ($self, $args) = @_;
- $args->{schema}->{bugmail_filters} = {
+ my ($self, $args) = @_;
+ $args->{schema}->{bugmail_filters} = {
+ FIELDS => [
+ id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1,},
+ user_id => {
+ TYPE => 'INT3',
+ NOTNULL => 1,
+ REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'},
+ },
+ field_name => {
+
+ # due to fake fields, this can't be field_id
+ TYPE => 'VARCHAR(64)',
+ NOTNULL => 0,
+ },
+ product_id => {
+ TYPE => 'INT2',
+ NOTNULL => 0,
+ REFERENCES => {TABLE => 'products', COLUMN => 'id', DELETE => 'CASCADE'},
+ },
+ component_id => {
+ TYPE => 'INT2',
+ NOTNULL => 0,
+ REFERENCES => {TABLE => 'components', COLUMN => 'id', DELETE => 'CASCADE'},
+ },
+ changer_id => {
+ TYPE => 'INT3',
+ NOTNULL => 0,
+ REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE'},
+ },
+ relationship => {TYPE => 'INT2', NOTNULL => 0,},
+ action => {TYPE => 'INT1', NOTNULL => 1,},
+ ],
+ INDEXES => [
+ bugmail_filters_unique_idx => {
FIELDS => [
- id => {
- TYPE => 'INTSERIAL',
- NOTNULL => 1,
- PRIMARYKEY => 1,
- },
- user_id => {
- TYPE => 'INT3',
- NOTNULL => 1,
- REFERENCES => {
- TABLE => 'profiles',
- COLUMN => 'userid',
- DELETE => 'CASCADE'
- },
- },
- field_name => {
- # due to fake fields, this can't be field_id
- TYPE => 'VARCHAR(64)',
- NOTNULL => 0,
- },
- product_id => {
- TYPE => 'INT2',
- NOTNULL => 0,
- REFERENCES => {
- TABLE => 'products',
- COLUMN => 'id',
- DELETE => 'CASCADE'
- },
- },
- component_id => {
- TYPE => 'INT2',
- NOTNULL => 0,
- REFERENCES => {
- TABLE => 'components',
- COLUMN => 'id',
- DELETE => 'CASCADE'
- },
- },
- changer_id => {
- TYPE => 'INT3',
- NOTNULL => 0,
- REFERENCES => {
- TABLE => 'profiles',
- COLUMN => 'userid',
- DELETE => 'CASCADE'
- },
- },
- relationship => {
- TYPE => 'INT2',
- NOTNULL => 0,
- },
- action => {
- TYPE => 'INT1',
- NOTNULL => 1,
- },
+ qw( user_id field_name product_id component_id
+ relationship )
],
- INDEXES => [
- bugmail_filters_unique_idx => {
- FIELDS => [ qw( user_id field_name product_id component_id
- relationship ) ],
- TYPE => 'UNIQUE',
- },
- bugmail_filters_user_idx => [
- 'user_id',
- ],
- ],
- };
+ TYPE => 'UNIQUE',
+ },
+ bugmail_filters_user_idx => ['user_id',],
+ ],
+ };
}
sub install_update_db {
- Bugzilla->dbh->bz_add_column(
- 'bugmail_filters',
- 'changer_id',
- {
- TYPE => 'INT3',
- NOTNULL => 0,
- }
- );
+ Bugzilla->dbh->bz_add_column('bugmail_filters', 'changer_id',
+ {TYPE => 'INT3', NOTNULL => 0,});
}
sub db_sanitize {
- my $dbh = Bugzilla->dbh;
- print "Deleting bugmail filters...\n";
- $dbh->do("DELETE FROM bugmail_filters");
+ my $dbh = Bugzilla->dbh;
+ print "Deleting bugmail filters...\n";
+ $dbh->do("DELETE FROM bugmail_filters");
}
__PACKAGE__->NAME;
diff --git a/extensions/BugmailFilter/lib/Constants.pm b/extensions/BugmailFilter/lib/Constants.pm
index a6636dda7..bed8a37d3 100644
--- a/extensions/BugmailFilter/lib/Constants.pm
+++ b/extensions/BugmailFilter/lib/Constants.pm
@@ -14,10 +14,10 @@ use warnings;
use base qw(Exporter);
our @EXPORT = qw(
- FAKE_FIELD_NAMES
- IGNORE_FIELDS
- FIELD_DESCRIPTION_OVERRIDE
- FILTER_RELATIONSHIPS
+ FAKE_FIELD_NAMES
+ IGNORE_FIELDS
+ FIELD_DESCRIPTION_OVERRIDE
+ FILTER_RELATIONSHIPS
);
use Bugzilla::Constants;
@@ -26,98 +26,54 @@ use Bugzilla::Constants;
# header but are not real fields
use constant FAKE_FIELD_NAMES => [
- {
- name => 'comment.created',
- description => 'Comment created',
- },
- {
- name => 'attachment.created',
- description => 'Attachment created',
- },
+ {name => 'comment.created', description => 'Comment created',},
+ {name => 'attachment.created', description => 'Attachment created',},
];
# these fields don't make any sense to filter on
use constant IGNORE_FIELDS => qw(
- assignee_last_login
- attach_data.thedata
- attachments.submitter
- cf_last_resolved
- commenter
- comment_tag
- creation_ts
- days_elapsed
- delta_ts
- everconfirmed
- last_visit_ts
- longdesc
- longdescs.count
- owner_idle_time
- reporter
- reporter_accessible
- setters.login_name
- tag
- votes
+ assignee_last_login
+ attach_data.thedata
+ attachments.submitter
+ cf_last_resolved
+ commenter
+ comment_tag
+ creation_ts
+ days_elapsed
+ delta_ts
+ everconfirmed
+ last_visit_ts
+ longdesc
+ longdescs.count
+ owner_idle_time
+ reporter
+ reporter_accessible
+ setters.login_name
+ tag
+ votes
);
# override the description of some fields
-use constant FIELD_DESCRIPTION_OVERRIDE => {
- bug_id => 'Bug Created',
-};
+use constant FIELD_DESCRIPTION_OVERRIDE => {bug_id => 'Bug Created',};
# relationship / int mappings
# _should_drop() also needs updating when this const is changed
use constant FILTER_RELATIONSHIPS => [
- {
- name => 'Assignee',
- value => 1,
- },
- {
- name => 'Not Assignee',
- value => 2,
- },
- {
- name => 'Reporter',
- value => 3,
- },
- {
- name => 'Not Reporter',
- value => 4,
- },
- {
- name => 'QA Contact',
- value => 5,
- },
- {
- name => 'Not QA Contact',
- value => 6,
- },
- {
- name => "CC'ed",
- value => 7,
- },
- {
- name => "Not CC'ed",
- value => 8,
- },
- {
- name => 'Watching',
- value => 9,
- },
- {
- name => 'Not Watching',
- value => 10,
- },
- {
- name => 'Mentoring',
- value => 11,
- },
- {
- name => 'Not Mentoring',
- value => 12,
- },
+ {name => 'Assignee', value => 1,},
+ {name => 'Not Assignee', value => 2,},
+ {name => 'Reporter', value => 3,},
+ {name => 'Not Reporter', value => 4,},
+ {name => 'QA Contact', value => 5,},
+ {name => 'Not QA Contact', value => 6,},
+ {name => "CC'ed", value => 7,},
+ {name => "Not CC'ed", value => 8,},
+ {name => 'Watching', value => 9,},
+ {name => 'Not Watching', value => 10,},
+ {name => 'Mentoring', value => 11,},
+ {name => 'Not Mentoring', value => 12,},
];
1;
diff --git a/extensions/BugmailFilter/lib/FakeField.pm b/extensions/BugmailFilter/lib/FakeField.pm
index e9f8b1808..cf82aec85 100644
--- a/extensions/BugmailFilter/lib/FakeField.pm
+++ b/extensions/BugmailFilter/lib/FakeField.pm
@@ -16,8 +16,8 @@ use Bugzilla::Extension::BugmailFilter::Constants;
# object
sub new {
- my ($class, $params) = @_;
- return bless($params, $class);
+ my ($class, $params) = @_;
+ return bless($params, $class);
}
sub name { $_[0]->{name} }
@@ -26,33 +26,35 @@ sub description { $_[0]->{description} }
# static methods
sub fake_fields {
- my $cache = Bugzilla->request_cache->{bugmail_filter};
- if (!$cache->{fake_fields}) {
- my @fields;
- foreach my $rh (@{ FAKE_FIELD_NAMES() }) {
- push @fields, Bugzilla::Extension::BugmailFilter::FakeField->new($rh);
- }
- $cache->{fake_fields} = \@fields;
+ my $cache = Bugzilla->request_cache->{bugmail_filter};
+ if (!$cache->{fake_fields}) {
+ my @fields;
+ foreach my $rh (@{FAKE_FIELD_NAMES()}) {
+ push @fields, Bugzilla::Extension::BugmailFilter::FakeField->new($rh);
}
- return $cache->{fake_fields};
+ $cache->{fake_fields} = \@fields;
+ }
+ return $cache->{fake_fields};
}
sub tracking_flag_fields {
- my $cache = Bugzilla->request_cache->{bugmail_filter};
- if (!$cache->{tracking_flag_fields}) {
- require Bugzilla::Extension::TrackingFlags::Constants;
- my @fields;
- my $tracking_types = Bugzilla::Extension::TrackingFlags::Constants::FLAG_TYPES();
- foreach my $tracking_type (@$tracking_types) {
- push @fields, Bugzilla::Extension::BugmailFilter::FakeField->new({
- name => 'tracking.' . $tracking_type->{name},
- description => $tracking_type->{description},
- sortkey => $tracking_type->{sortkey},
- });
- }
- $cache->{tracking_flag_fields} = \@fields;
+ my $cache = Bugzilla->request_cache->{bugmail_filter};
+ if (!$cache->{tracking_flag_fields}) {
+ require Bugzilla::Extension::TrackingFlags::Constants;
+ my @fields;
+ my $tracking_types
+ = Bugzilla::Extension::TrackingFlags::Constants::FLAG_TYPES();
+ foreach my $tracking_type (@$tracking_types) {
+ push @fields,
+ Bugzilla::Extension::BugmailFilter::FakeField->new({
+ name => 'tracking.' . $tracking_type->{name},
+ description => $tracking_type->{description},
+ sortkey => $tracking_type->{sortkey},
+ });
}
- return $cache->{tracking_flag_fields};
+ $cache->{tracking_flag_fields} = \@fields;
+ }
+ return $cache->{tracking_flag_fields};
}
1;
diff --git a/extensions/BugmailFilter/lib/Filter.pm b/extensions/BugmailFilter/lib/Filter.pm
index 7f2f4cb87..fa2c708cd 100644
--- a/extensions/BugmailFilter/lib/Filter.pm
+++ b/extensions/BugmailFilter/lib/Filter.pm
@@ -25,14 +25,14 @@ use Bugzilla::Util qw(trim);
use constant DB_TABLE => 'bugmail_filters';
use constant DB_COLUMNS => qw(
- id
- user_id
- product_id
- component_id
- field_name
- relationship
- changer_id
- action
+ id
+ user_id
+ product_id
+ component_id
+ field_name
+ relationship
+ changer_id
+ action
);
use constant LIST_ORDER => 'id';
@@ -40,13 +40,11 @@ use constant LIST_ORDER => 'id';
use constant UPDATE_COLUMNS => ();
use constant VALIDATORS => {
- user_id => \&_check_user,
- field_name => \&_check_field_name,
- action => \&Bugzilla::Object::check_boolean,
-};
-use constant VALIDATOR_DEPENDENCIES => {
- component_id => [ 'product_id' ],
+ user_id => \&_check_user,
+ field_name => \&_check_field_name,
+ action => \&Bugzilla::Object::check_boolean,
};
+use constant VALIDATOR_DEPENDENCIES => {component_id => ['product_id'],};
use constant AUDIT_CREATES => 0;
use constant AUDIT_UPDATES => 0;
@@ -56,163 +54,164 @@ use constant USE_MEMCACHED => 0;
# getters
sub user {
- my ($self) = @_;
- return Bugzilla::User->new({ id => $self->{user_id}, cache => 1 });
+ my ($self) = @_;
+ return Bugzilla::User->new({id => $self->{user_id}, cache => 1});
}
sub product {
- my ($self) = @_;
- return $self->{product_id}
- ? Bugzilla::Product->new({ id => $self->{product_id}, cache => 1 })
- : undef;
+ my ($self) = @_;
+ return $self->{product_id}
+ ? Bugzilla::Product->new({id => $self->{product_id}, cache => 1})
+ : undef;
}
sub product_name {
- my ($self) = @_;
- return $self->{product_name} //= $self->{product_id} ? $self->product->name : '';
+ my ($self) = @_;
+ return $self->{product_name}
+ //= $self->{product_id} ? $self->product->name : '';
}
sub component {
- my ($self) = @_;
- return $self->{component_id}
- ? Bugzilla::Component->new({ id => $self->{component_id}, cache => 1 })
- : undef;
+ my ($self) = @_;
+ return $self->{component_id}
+ ? Bugzilla::Component->new({id => $self->{component_id}, cache => 1})
+ : undef;
}
sub component_name {
- my ($self) = @_;
- return $self->{component_name} //= $self->{component_id} ? $self->component->name : '';
+ my ($self) = @_;
+ return $self->{component_name}
+ //= $self->{component_id} ? $self->component->name : '';
}
sub field_name {
- return $_[0]->{field_name} //= '';
+ return $_[0]->{field_name} //= '';
}
sub field_description {
- my ($self, $value) = @_;
- $self->{field_description} = $value if defined($value);
- return $self->{field_description};
+ my ($self, $value) = @_;
+ $self->{field_description} = $value if defined($value);
+ return $self->{field_description};
}
sub field {
- my ($self) = @_;
- return unless $self->{field_name};
- if (!$self->{field}) {
- if (substr($self->{field_name}, 0, 1) eq '~') {
- # this should never happen
- die "not implemented";
- }
- foreach my $field (
- @{ Bugzilla::Extension::BugmailFilter::FakeField->fake_fields() },
- @{ Bugzilla::Extension::BugmailFilter::FakeField->tracking_flag_fields() },
- ) {
- if ($field->{name} eq $self->{field_name}) {
- return $self->{field} = $field;
- }
- }
- $self->{field} = Bugzilla::Field->new({ name => $self->{field_name}, cache => 1 });
+ my ($self) = @_;
+ return unless $self->{field_name};
+ if (!$self->{field}) {
+ if (substr($self->{field_name}, 0, 1) eq '~') {
+
+ # this should never happen
+ die "not implemented";
}
- return $self->{field};
+ foreach my $field (
+ @{Bugzilla::Extension::BugmailFilter::FakeField->fake_fields()},
+ @{Bugzilla::Extension::BugmailFilter::FakeField->tracking_flag_fields()},
+ )
+ {
+ if ($field->{name} eq $self->{field_name}) {
+ return $self->{field} = $field;
+ }
+ }
+ $self->{field}
+ = Bugzilla::Field->new({name => $self->{field_name}, cache => 1});
+ }
+ return $self->{field};
}
sub relationship {
- return $_[0]->{relationship};
+ return $_[0]->{relationship};
}
sub changer_id {
- return $_[0]->{changer_id};
+ return $_[0]->{changer_id};
}
sub changer {
- my ($self) = @_;
- return $self->{changer_id}
- ? Bugzilla::User->new({ id => $self->{changer_id}, cache => 1 })
- : undef;
+ my ($self) = @_;
+ return $self->{changer_id}
+ ? Bugzilla::User->new({id => $self->{changer_id}, cache => 1})
+ : undef;
}
sub relationship_name {
- my ($self) = @_;
- foreach my $rel (@{ FILTER_RELATIONSHIPS() }) {
- return $rel->{name}
- if $rel->{value} == $self->{relationship};
- }
- return '?';
+ my ($self) = @_;
+ foreach my $rel (@{FILTER_RELATIONSHIPS()}) {
+ return $rel->{name} if $rel->{value} == $self->{relationship};
+ }
+ return '?';
}
sub is_exclude {
- return $_[0]->{action} == 1;
+ return $_[0]->{action} == 1;
}
sub is_include {
- return $_[0]->{action} == 0;
+ return $_[0]->{action} == 0;
}
# validators
sub _check_user {
- my ($class, $user) = @_;
- $user || ThrowCodeError('param_required', { param => 'user' });
+ my ($class, $user) = @_;
+ $user || ThrowCodeError('param_required', {param => 'user'});
}
sub _check_field_name {
- my ($class, $field_name) = @_;
- return undef unless $field_name;
- if (substr($field_name, 0, 1) eq '~') {
- $field_name = lc(trim($field_name));
- $field_name =~ /^~[a-z0-9_\.\-]+$/
- || ThrowUserError('bugmail_filter_invalid');
- length($field_name) <= 64
- || ThrowUserError('bugmail_filter_too_long');
- return $field_name;
- }
- foreach my $rh (@{ FAKE_FIELD_NAMES() }) {
- return $field_name if $rh->{name} eq $field_name;
- }
- return $field_name
- if $field_name =~ /^tracking\./;
- Bugzilla::Field->check({ name => $field_name, cache => 1});
+ my ($class, $field_name) = @_;
+ return undef unless $field_name;
+ if (substr($field_name, 0, 1) eq '~') {
+ $field_name = lc(trim($field_name));
+ $field_name =~ /^~[a-z0-9_\.\-]+$/ || ThrowUserError('bugmail_filter_invalid');
+ length($field_name) <= 64 || ThrowUserError('bugmail_filter_too_long');
return $field_name;
+ }
+ foreach my $rh (@{FAKE_FIELD_NAMES()}) {
+ return $field_name if $rh->{name} eq $field_name;
+ }
+ return $field_name if $field_name =~ /^tracking\./;
+ Bugzilla::Field->check({name => $field_name, cache => 1});
+ return $field_name;
}
# methods
sub matches {
- my ($self, $args) = @_;
-
- if (my $field_name = $self->{field_name}) {
- if ($args->{field}->{field_name} && substr($field_name, 0, 1) eq '~') {
- my $substring = quotemeta(substr($field_name, 1));
- if ($args->{field}->{filter_field} !~ /$substring/i) {
- return 0;
- }
- }
- elsif ($field_name eq 'flagtypes.name') {
- if ($args->{field}->{field_name} ne $field_name) {
- return 0;
- }
- }
- elsif ($field_name ne $args->{field}->{filter_field}) {
- return 0;
- }
- }
+ my ($self, $args) = @_;
- if ($self->{product_id} && $self->{product_id} != $args->{product_id}) {
+ if (my $field_name = $self->{field_name}) {
+ if ($args->{field}->{field_name} && substr($field_name, 0, 1) eq '~') {
+ my $substring = quotemeta(substr($field_name, 1));
+ if ($args->{field}->{filter_field} !~ /$substring/i) {
return 0;
+ }
}
-
- if ($self->{component_id} && $self->{component_id} != $args->{component_id}) {
+ elsif ($field_name eq 'flagtypes.name') {
+ if ($args->{field}->{field_name} ne $field_name) {
return 0;
+ }
}
-
- if ($self->{relationship} && !$args->{rel_map}->[$self->{relationship}]) {
- return 0;
+ elsif ($field_name ne $args->{field}->{filter_field}) {
+ return 0;
}
+ }
- if ($self->{changer_id} && $self->{changer_id} != $args->{changer_id}) {
- return 0;
- }
+ if ($self->{product_id} && $self->{product_id} != $args->{product_id}) {
+ return 0;
+ }
+
+ if ($self->{component_id} && $self->{component_id} != $args->{component_id}) {
+ return 0;
+ }
+
+ if ($self->{relationship} && !$args->{rel_map}->[$self->{relationship}]) {
+ return 0;
+ }
+
+ if ($self->{changer_id} && $self->{changer_id} != $args->{changer_id}) {
+ return 0;
+ }
- return 1;
+ return 1;
}
1;