From a4601960dedb6012dd12e6a6fe47de7fc6af6965 Mon Sep 17 00:00:00 2001 From: Simon Green Date: Thu, 15 Sep 2016 18:44:54 +1000 Subject: Bug 65388 - Make it possible to query for open bugs with an inactive target milestone --- Bugzilla/Search.pm | 94 +++++++++++++++++++++- template/en/default/global/field-descs.none.tmpl | 2 + template/en/default/list/list.html.tmpl | 3 +- .../en/default/search/boolean-charts.html.tmpl | 2 + 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index b922f5845..b806ff8da 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -163,6 +163,8 @@ use constant OPERATORS => { changedby => \&_changedby, isempty => \&_isempty, isnotempty => \&_isnotempty, + isactive => \&_isactive, + isnotactive => \&_isactive, }; # Some operators are really just standard SQL operators, and are @@ -191,6 +193,8 @@ use constant OPERATOR_REVERSE => { greaterthaneq => 'lessthan', isempty => 'isnotempty', isnotempty => 'isempty', + isactive => 'isnotactive', + isnotactive => 'isactive', # The following don't currently have reversals: # casesubstring, anyexact, allwords, allwordssubstr }; @@ -210,6 +214,8 @@ use constant NON_NUMERIC_OPERATORS => qw( use constant NO_VALUE_OPERATORS => qw( isempty isnotempty + isactive + isnotactive ); use constant MULTI_SELECT_OVERRIDE => { @@ -936,6 +942,16 @@ sub _multi_select_fields { return $self->{multi_select_fields}; } +# Select custom fields have an active field, so we need to know these fields +# too. The type is important as we handle them differently. +sub _select_fields { + my ($self) = @_; + $self->{select_fields} ||= Bugzilla->fields({ + by_name => 1, + type => [FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_SINGLE_SELECT]}); + return $self->{select_fields}; +} + # $self->{params} contains values that could be undef, could be a string, # or could be an arrayref. Sometimes we want that value as an array, # always. @@ -2478,7 +2494,7 @@ sub _user_nonchanged { # For negative operators, the system we're using here # only works properly if we reverse the operator and check IS NULL # in the WHERE. - my $is_negative = $operator =~ /^(?:no|isempty)/ ? 1 : 0; + my $is_negative = $operator ne 'notactive' && $operator =~ /^(?:no|isempty)/ ? 1 : 0; if ($is_negative) { $args->{operator} = $self->_reverse_operator($operator); } @@ -2613,6 +2629,10 @@ sub _long_desc_nonchanged { $args->{term} = $self->_multiselect_isempty($args, $operator eq 'isnotempty'); return; } + if ($operator =~ /^is(not)?active$/) { + # Comments can't be (in)active + $self->_invalid_combination($args); + } my $dbh = Bugzilla->dbh; my $table = "longdescs_$chart_id"; @@ -2948,7 +2968,7 @@ sub _flagtypes_nonchanged { # If you search for "Flags" (does not contain) "approval+" we actually want # to return *bugs* that don't contain an approval+ flag. Without rewriting # the negation we'll search for *flags* which don't contain approval+. - if ($operator =~ s/^not//) { + if ($operator ne 'notactive' && $operator =~ s/^not//) { $args->{operator} = $operator; $condition->operator($operator); $condition->negate(1); @@ -3441,6 +3461,76 @@ sub _empty_value { return "''"; } +sub _isactive { + my ($self, $args) = @_; + my ($field, $chart_id, $operator, $joins, $bugs_table) = + @$args{qw(field chart_id operator joins bugs_table)}; + + my $value = $operator eq 'isnotactive' ? 0 : 1; + + my @simple_fields = qw(bug_severity bug_status op_sys priority rep_platform + resolution version + ); + my @user_fields = qw(attachments.submitter assigned_to assigned_to_realname + cc commenter reporter reporter_realname requestees.login_name + setters.login_name qa_contact qa_contact_realname + ); + + if ($field eq 'product' or $field eq 'component') { + $args->{term} = "${field}s.isactive = $value"; + } + elsif (grep {$_ eq $field} @simple_fields) { + push @$joins, { + table => ($field eq 'version' ? 'versions' : $field), + as => "${field}_$chart_id", + from => $field, + to => 'value', + }; + $args->{term} = "${field}_$chart_id.isactive = $value"; + } + elsif ($field eq 'flagtypes.name') { + $args->{term} = "flagtypes_$chart_id.is_active = $value"; + } + elsif ($field eq 'bug_group') { + $args->{term} = "groups.isactive = $value"; + } + elsif ($field eq 'keywords') { + $args->{term} = "keyworddefs.is_active = $value"; + } + elsif ($field eq 'target_milestone') { + push @$joins, { + table => 'milestones', + as => "milestones_$chart_id", + from => 'target_milestone', + to => 'value', + }; + $args->{term} = qq{ + (milestones_$chart_id.product_id = bugs.product_id AND + milestones_$chart_id.isactive = $value) + }; + } + elsif (grep {$_ eq $field} @user_fields) { + my $as = "name_${field}_$chart_id"; + # For fields with periods in their name. + $as =~ s/\./_/; + $args->{full_field} = "$as.disabled_text"; + my $op = $value ? '=' : '!='; + $args->{term} = "$as.disabledtext $op ''"; + } + + elsif (my $field_obj = $self->_select_fields->{$field}) { + my $field_type = $field_obj->type; + $args->{term} = $field_type == FIELD_TYPE_MULTI_SELECT + ? 'value' + : "bugs.$field"; + $args->{term} .= " IN (SELECT value FROM $field WHERE $field.isactive = $value)"; + } + else { + # This field does not have an active value + $self->_invalid_combination($args); + } +} + ###################### # Public Subroutines # ###################### diff --git a/template/en/default/global/field-descs.none.tmpl b/template/en/default/global/field-descs.none.tmpl index f4e17c3f8..e6c947104 100644 --- a/template/en/default/global/field-descs.none.tmpl +++ b/template/en/default/global/field-descs.none.tmpl @@ -37,6 +37,8 @@ "notmatches" => "does not match", "isempty" => "is empty", "isnotempty" => "is not empty", + "isactive" => "is active", + "isnotactive" => "is not active", } %] [% field_types = { ${constants.FIELD_TYPE_UNKNOWN} => "Unknown Type", diff --git a/template/en/default/list/list.html.tmpl b/template/en/default/list/list.html.tmpl index 190486b12..9cb3f1357 100644 --- a/template/en/default/list/list.html.tmpl +++ b/template/en/default/list/list.html.tmpl @@ -104,7 +104,8 @@ 'notequals', 'regexp', 'notregexp', 'lessthan', 'lessthaneq', 'greaterthan', 'greaterthaneq', 'changedbefore', 'changedafter', 'changedfrom', 'changedto', 'changedby', 'notsubstring', 'nowords', - 'nowordssubstr', 'notmatches', 'isempty', 'isnotempty' + 'nowordssubstr', 'notmatches', 'isempty', 'isnotempty', 'isactive', + 'isnotactive' ] %] Hide Search Description diff --git a/template/en/default/search/boolean-charts.html.tmpl b/template/en/default/search/boolean-charts.html.tmpl index bfb4e7bf1..5e1742a5c 100644 --- a/template/en/default/search/boolean-charts.html.tmpl +++ b/template/en/default/search/boolean-charts.html.tmpl @@ -35,6 +35,8 @@ "notmatches", "isempty", "isnotempty", + "isactive", + "isnotactive", ] %]
-- cgit v1.2.3-24-g4f1b