Commit d5c5177f authored by Max Kanat-Alexander's avatar Max Kanat-Alexander

Bug 640045: Convert Search.pm to use the new AND/OR system internally.

This includes creating new Search::Clause and Search::Condition objects. r=mkanat, a=mkanat (module owner)
parent 14151ea2
...@@ -49,6 +49,7 @@ use Bugzilla::Constants; ...@@ -49,6 +49,7 @@ use Bugzilla::Constants;
use Bugzilla::Group; use Bugzilla::Group;
use Bugzilla::User; use Bugzilla::User;
use Bugzilla::Field; use Bugzilla::Field;
use Bugzilla::Search::Clause;
use Bugzilla::Status; use Bugzilla::Status;
use Bugzilla::Keyword; use Bugzilla::Keyword;
...@@ -125,7 +126,6 @@ use Storable qw(dclone); ...@@ -125,7 +126,6 @@ use Storable qw(dclone);
# bar@blah.org # bar@blah.org
# -------------------------------------------------------------- # --------------------------------------------------------------
############# #############
# Constants # # Constants #
############# #############
...@@ -400,10 +400,6 @@ use constant FIELD_MAP => { ...@@ -400,10 +400,6 @@ use constant FIELD_MAP => {
# <none> for the X, Y, or Z axis in report.cgi. # <none> for the X, Y, or Z axis in report.cgi.
use constant EMPTY_COLUMN => '-1'; use constant EMPTY_COLUMN => '-1';
# A special value that is pushed into charts during _params_to_charts to
# represent that the particular chart we're dealing with should be negated.
use constant NEGATE => 'NOT';
# Some fields are not sorted on themselves, but on other fields. # Some fields are not sorted on themselves, but on other fields.
# We need to have a list of these fields and what they map to. # We need to have a list of these fields and what they map to.
use constant SPECIAL_ORDER => { use constant SPECIAL_ORDER => {
...@@ -694,14 +690,12 @@ sub sql { ...@@ -694,14 +690,12 @@ sub sql {
return $self->{sql} if $self->{sql}; return $self->{sql} if $self->{sql};
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
my ($joins, $having_terms, $where_terms) = $self->_charts_to_conditions(); my ($joins, $clause) = $self->_charts_to_conditions();
my $select = join(', ', $self->_sql_select); my $select = join(', ', $self->_sql_select);
my $from = $self->_sql_from($joins); my $from = $self->_sql_from($joins);
my $where = $self->_sql_where($where_terms); my $where = $self->_sql_where($clause);
my $group_by = $dbh->sql_group_by($self->_sql_group_by); my $group_by = $dbh->sql_group_by($self->_sql_group_by);
my $having = @$having_terms
? "\nHAVING " . join(' AND ', @$having_terms) : '';
my $order_by = $self->_sql_order_by my $order_by = $self->_sql_order_by
? "\nORDER BY " . join(', ', $self->_sql_order_by) : ''; ? "\nORDER BY " . join(', ', $self->_sql_order_by) : '';
my $limit = $self->_sql_limit; my $limit = $self->_sql_limit;
...@@ -711,7 +705,7 @@ sub sql { ...@@ -711,7 +705,7 @@ sub sql {
SELECT $select SELECT $select
FROM $from FROM $from
WHERE $where WHERE $where
$group_by$having$order_by$limit $group_by$order_by$limit
END END
$self->{sql} = $query; $self->{sql} = $query;
return $self->{sql}; return $self->{sql};
...@@ -1135,13 +1129,15 @@ sub _standard_where { ...@@ -1135,13 +1129,15 @@ sub _standard_where {
my $user = $self->_user; my $user = $self->_user;
if ($user->id) { if ($user->id) {
my $userid = $user->id; my $userid = $user->id;
# This indentation makes the resulting SQL more readable.
$security_term .= <<END; $security_term .= <<END;
OR (bugs.reporter_accessible = 1 AND bugs.reporter = $userid)
OR (bugs.cclist_accessible = 1 AND security_cc.who IS NOT NULL) OR (bugs.reporter_accessible = 1 AND bugs.reporter = $userid)
OR bugs.assigned_to = $userid OR (bugs.cclist_accessible = 1 AND security_cc.who IS NOT NULL)
OR bugs.assigned_to = $userid
END END
if (Bugzilla->params->{'useqacontact'}) { if (Bugzilla->params->{'useqacontact'}) {
$security_term.= " OR bugs.qa_contact = $userid"; $security_term.= " OR bugs.qa_contact = $userid";
} }
$security_term = "($security_term)"; $security_term = "($security_term)";
} }
...@@ -1152,10 +1148,15 @@ END ...@@ -1152,10 +1148,15 @@ END
} }
sub _sql_where { sub _sql_where {
my ($self, $where_terms) = @_; my ($self, $main_clause) = @_;
# The newline and this particular spacing makes the resulting # The newline and this particular spacing makes the resulting
# SQL a bit more readable for debugging. # SQL a bit more readable for debugging.
return join("\n AND ", $self->_standard_where, @$where_terms); my $where = join("\n AND ", $self->_standard_where);
my $clause_sql = $main_clause->as_string;
if ($clause_sql) {
$where .= "\n AND " . $clause_sql;
}
return $where;
} }
################################ ################################
...@@ -1224,35 +1225,6 @@ sub _convert_old_params { ...@@ -1224,35 +1225,6 @@ sub _convert_old_params {
} }
} }
sub _convert_special_params_to_chart_params {
my ($self) = @_;
my $params = $self->_params;
my @special_charts = $self->_special_charts();
# First we delete any sign of "Chart #-1" from the input parameters,
# because we want to guarantee the user didn't hide something there.
my @badcharts = grep { /^(field|type|value)-1-/ } keys %$params;
foreach my $field (@badcharts) {
delete $params->{$field};
}
# now we take our special chart and stuff it into the form hash
my $chart = -1;
my $and = 0;
foreach my $or_array (@special_charts) {
my $or = 0;
while (@$or_array) {
my $identifier = "$chart-$and-$or";
$params->{"field$identifier"} = shift @$or_array;
$params->{"type$identifier"} = shift @$or_array;
$params->{"value$identifier"} = shift @$or_array;
$or++;
}
$and++;
}
}
# This parses all the standard search parameters except for the boolean # This parses all the standard search parameters except for the boolean
# charts. # charts.
sub _special_charts { sub _special_charts {
...@@ -1260,11 +1232,12 @@ sub _special_charts { ...@@ -1260,11 +1232,12 @@ sub _special_charts {
$self->_convert_old_params(); $self->_convert_old_params();
$self->_special_parse_bug_status(); $self->_special_parse_bug_status();
$self->_special_parse_resolution(); $self->_special_parse_resolution();
my @charts = $self->_parse_basic_fields(); my $clause = new Bugzilla::Search::Clause();
push(@charts, $self->_special_parse_email()); $clause->add( $self->_parse_basic_fields() );
push(@charts, $self->_special_parse_chfield()); $clause->add( $self->_special_parse_email() );
push(@charts, $self->_special_parse_deadline()); $clause->add( $self->_special_parse_chfield() );
return @charts; $clause->add( $self->_special_parse_deadline() );
return $clause;
} }
sub _parse_basic_fields { sub _parse_basic_fields {
...@@ -1272,7 +1245,7 @@ sub _parse_basic_fields { ...@@ -1272,7 +1245,7 @@ sub _parse_basic_fields {
my $params = $self->_params; my $params = $self->_params;
my $chart_fields = $self->_chart_fields; my $chart_fields = $self->_chart_fields;
my @charts; my $clause = new Bugzilla::Search::Clause();
foreach my $field_name (keys %$chart_fields) { foreach my $field_name (keys %$chart_fields) {
# CGI params shouldn't have periods in them, so we only accept # CGI params shouldn't have periods in them, so we only accept
# period-separated fields with underscores where the periods go. # period-separated fields with underscores where the periods go.
...@@ -1296,9 +1269,9 @@ sub _parse_basic_fields { ...@@ -1296,9 +1269,9 @@ sub _parse_basic_fields {
else { else {
$pass_value = join(',', @values); $pass_value = join(',', @values);
} }
push(@charts, [$field_name, $operator, $pass_value]); $clause->add($field_name, $operator, $pass_value);
} }
return @charts; return $clause;
} }
sub _special_parse_bug_status { sub _special_parse_bug_status {
...@@ -1358,7 +1331,8 @@ sub _special_parse_chfield { ...@@ -1358,7 +1331,8 @@ sub _special_parse_chfield {
@fields = map { $_ eq '[Bug creation]' ? 'creation_ts' : $_ } @fields; @fields = map { $_ eq '[Bug creation]' ? 'creation_ts' : $_ } @fields;
my @charts; my $clause = new Bugzilla::Search::Clause();
# It is always safe and useful to push delta_ts into the charts # It is always safe and useful to push delta_ts into the charts
# if there is a "from" date specified. It doesn't conflict with # if there is a "from" date specified. It doesn't conflict with
# searching [Bug creation], because a bug's delta_ts is set to # searching [Bug creation], because a bug's delta_ts is set to
...@@ -1366,7 +1340,7 @@ sub _special_parse_chfield { ...@@ -1366,7 +1340,7 @@ sub _special_parse_chfield {
# database an additional index to possibly choose, on a table that # database an additional index to possibly choose, on a table that
# is smaller than bugs_activity. # is smaller than bugs_activity.
if ($date_from ne '') { if ($date_from ne '') {
push(@charts, ['delta_ts', 'greaterthaneq', $date_from]); $clause->add('delta_ts', 'greaterthaneq', $date_from);
} }
# It's not normally safe to do it for "to" dates, though--"chfieldto" means # It's not normally safe to do it for "to" dates, though--"chfieldto" means
# "a field that changed before this date", and delta_ts could be either # "a field that changed before this date", and delta_ts could be either
...@@ -1375,7 +1349,7 @@ sub _special_parse_chfield { ...@@ -1375,7 +1349,7 @@ sub _special_parse_chfield {
# chfield, means "just search delta_ts", and so we still want that to # chfield, means "just search delta_ts", and so we still want that to
# work. # work.
if ($date_to ne '' and !@fields and $value_to eq '') { if ($date_to ne '' and !@fields and $value_to eq '') {
push(@charts, ['delta_ts', 'lessthaneq', $date_to]); $clause->add('delta_ts', 'lessthaneq', $date_to);
} }
# Basically, we construct the chart like: # Basically, we construct the chart like:
...@@ -1390,29 +1364,29 @@ sub _special_parse_chfield { ...@@ -1390,29 +1364,29 @@ sub _special_parse_chfield {
# change date of the fields. # change date of the fields.
if ($value_to ne '') { if ($value_to ne '') {
my @value_chart; my $value_clause = new Bugzilla::Search::Clause('OR');
foreach my $field (@fields) { foreach my $field (@fields) {
push(@value_chart, $field, 'changedto', $value_to); $value_clause->add($field, 'changedto', $value_to);
} }
push(@charts, \@value_chart) if @value_chart; $clause->add($value_clause);
} }
if ($date_from ne '') { if ($date_from ne '') {
my @date_from_chart; my $from_clause = new Bugzilla::Search::Clause('OR');
foreach my $field (@fields) { foreach my $field (@fields) {
push(@date_from_chart, $field, 'changedafter', $date_from); $from_clause->add($field, 'changedafter', $date_from);
} }
push(@charts, \@date_from_chart) if @date_from_chart; $clause->add($from_clause);
} }
if ($date_to ne '') { if ($date_to ne '') {
my @date_to_chart; my $to_clause = new Bugzilla::Search::Clause('OR');
foreach my $field (@fields) { foreach my $field (@fields) {
push(@date_to_chart, $field, 'changedbefore', $date_to); $to_clause->add($field, 'changedbefore', $date_to);
} }
push(@charts, \@date_to_chart) if @date_to_chart; $clause->add($to_clause);
} }
return @charts; return $clause;
} }
sub _special_parse_deadline { sub _special_parse_deadline {
...@@ -1420,15 +1394,15 @@ sub _special_parse_deadline { ...@@ -1420,15 +1394,15 @@ sub _special_parse_deadline {
return if !$self->_user->is_timetracker; return if !$self->_user->is_timetracker;
my $params = $self->_params; my $params = $self->_params;
my @charts; my $clause = new Bugzilla::Search::Clause();
if (my $from = $params->{'deadlinefrom'}) { if (my $from = $params->{'deadlinefrom'}) {
push(@charts, ['deadline', 'greaterthaneq', $from]); $clause->add('deadline', 'greaterthaneq', $from);
} }
if (my $to = $params->{'deadlineto'}) { if (my $to = $params->{'deadlineto'}) {
push(@charts, ['deadline', 'lessthaneq', $to]); $clause->add('deadline', 'lessthaneq', $to);
} }
return @charts; return $clause;
} }
sub _special_parse_email { sub _special_parse_email {
...@@ -1437,7 +1411,7 @@ sub _special_parse_email { ...@@ -1437,7 +1411,7 @@ sub _special_parse_email {
my @email_params = grep { $_ =~ /^email\d+$/ } keys %$params; my @email_params = grep { $_ =~ /^email\d+$/ } keys %$params;
my @charts; my $clause = new Bugzilla::Search::Clause();
foreach my $param (@email_params) { foreach my $param (@email_params) {
$param =~ /(\d+)$/; $param =~ /(\d+)$/;
my $id = $1; my $id = $1;
...@@ -1446,20 +1420,20 @@ sub _special_parse_email { ...@@ -1446,20 +1420,20 @@ sub _special_parse_email {
my $type = $params->{"emailtype$id"} || 'anyexact'; my $type = $params->{"emailtype$id"} || 'anyexact';
$type = "anyexact" if $type eq "exact"; $type = "anyexact" if $type eq "exact";
my @or_charts; my $or_clause = new Bugzilla::Search::Clause('OR');
foreach my $field (qw(assigned_to reporter cc qa_contact)) { foreach my $field (qw(assigned_to reporter cc qa_contact)) {
if ($params->{"email$field$id"}) { if ($params->{"email$field$id"}) {
push(@or_charts, $field, $type, $email); $or_clause->add($field, $type, $email);
} }
} }
if ($params->{"emaillongdesc$id"}) { if ($params->{"emaillongdesc$id"}) {
push(@or_charts, "commenter", $type, $email); $or_clause->add("commenter", $type, $email);
} }
push(@charts, \@or_charts); $clause->add($or_clause);
} }
return @charts; return $clause;
} }
sub _special_parse_resolution { sub _special_parse_resolution {
...@@ -1496,52 +1470,36 @@ sub _valid_values { ...@@ -1496,52 +1470,36 @@ sub _valid_values {
sub _charts_to_conditions { sub _charts_to_conditions {
my ($self) = @_; my ($self) = @_;
my @charts = $self->_params_to_charts();
my (@joins, @having, @where_terms);
foreach my $chart (@charts) { my $clause = $self->_charts;
my @and_terms; my @joins;
my $negate; $clause->walk_conditions(sub {
foreach my $and_item (@$chart) { my ($condition) = @_;
if (!ref $and_item and $and_item eq NEGATE) { return if !$condition->translated;
$negate = 1; push(@joins, @{ $condition->translated->{joins} });
next; });
} return (\@joins, $clause);
my @or_terms; }
foreach my $or_item (@$and_item) {
if ($or_item->{term} ne '') {
push(@or_terms, $or_item->{term});
}
push(@joins, @{ $or_item->{joins} });
push(@having, @{ $or_item->{having} });
}
if (@or_terms) {
# If a term contains ANDs, we need to put parens around the
# condition. This is a pretty weak test, but it's actually OK
# to put parens around too many things.
@or_terms = map { $_ =~ /\bAND\b/i ? "($_)" : $_ } @or_terms;
my $or_sql = join(' OR ', @or_terms);
push(@and_terms, $or_sql);
}
}
# And here we need to paren terms that contain ORs.
@and_terms = map { $_ =~ /\bOR\b/i ? "($_)" : $_ } @and_terms;
my $and_sql = join(' AND ', @and_terms);
if ($negate and $and_sql ne '') {
$and_sql = "NOT ($and_sql)";
}
push(@where_terms, $and_sql) if $and_sql ne '';
}
return (\@joins, \@having, \@where_terms); sub _charts {
my ($self) = @_;
my $clause = $self->_params_to_data_structure();
my $chart_id = 0;
$clause->walk_conditions(sub { $self->_handle_chart($chart_id++, @_) });
return $clause;
} }
sub _params_to_charts { sub _params_to_data_structure {
my ($self) = @_; my ($self) = @_;
# First we get the "special" charts, representing all the normal
# field son the search page. This may modify _params, so it needs to
# happen first.
my $clause = $self->_special_charts;
# Then we process the old Boolean Charts input format.
my $params = $self->_params; my $params = $self->_params;
$self->_convert_special_params_to_chart_params();
my @param_list = keys %$params; my @param_list = keys %$params;
my @all_field_params = grep { /^field-?\d+/ } @param_list; my @all_field_params = grep { /^field-?\d+/ } @param_list;
...@@ -1549,54 +1507,43 @@ sub _params_to_charts { ...@@ -1549,54 +1507,43 @@ sub _params_to_charts {
@chart_ids = sort { $a <=> $b } uniq @chart_ids; @chart_ids = sort { $a <=> $b } uniq @chart_ids;
my $sequence = 0; my $sequence = 0;
my @charts;
foreach my $chart_id (@chart_ids) { foreach my $chart_id (@chart_ids) {
my @all_and = grep { /^field$chart_id-\d+/ } @param_list; my @all_and = grep { /^field$chart_id-\d+/ } @param_list;
my @and_ids = map { /^field$chart_id-(\d+)/; $1 } @all_and; my @and_ids = map { /^field$chart_id-(\d+)/; $1 } @all_and;
@and_ids = sort { $a <=> $b } uniq @and_ids; @and_ids = sort { $a <=> $b } uniq @and_ids;
my @and_charts; my $and_clause = new Bugzilla::Search::Clause();
foreach my $and_id (@and_ids) { foreach my $and_id (@and_ids) {
my @all_or = grep { /^field$chart_id-$and_id-\d+/ } @param_list; my @all_or = grep { /^field$chart_id-$and_id-\d+/ } @param_list;
my @or_ids = map { /^field$chart_id-$and_id-(\d+)/; $1 } @all_or; my @or_ids = map { /^field$chart_id-$and_id-(\d+)/; $1 } @all_or;
@or_ids = sort { $a <=> $b } uniq @or_ids; @or_ids = sort { $a <=> $b } uniq @or_ids;
my @or_charts; my $or_clause = new Bugzilla::Search::Clause('OR');
foreach my $or_id (@or_ids) { foreach my $or_id (@or_ids) {
my $info = $self->_handle_chart($chart_id, $and_id, $or_id); my $identifier = "$chart_id-$and_id-$or_id";
# $info will be undefined if _handle_chart returned early, my $field = $params->{"field$identifier"};
# meaning that the field, value, or operator were empty. my $operator = $params->{"type$identifier"};
push(@or_charts, $info) if defined $info; my $value = $params->{"value$identifier"};
} $or_clause->add($field, $operator, $value);
if ($params->{"negate$chart_id"}) {
push(@and_charts, NEGATE);
} }
push(@and_charts, \@or_charts); $and_clause->add($or_clause);
$and_clause->negate(1) if $params->{"negate$chart_id"};
} }
push(@charts, \@and_charts); $clause->add($and_clause);
} }
return @charts; return $clause;
} }
sub _handle_chart { sub _handle_chart {
my ($self, $chart_id, $and_id, $or_id) = @_; my ($self, $chart_id, $condition) = @_;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
my $params = $self->_params; my $params = $self->_params;
my ($field, $operator, $value) = $condition->fov;
my $sql_chart_id = $chart_id;
if ($chart_id < 0) {
$sql_chart_id = "default_" . abs($chart_id);
}
my $identifier = "$chart_id-$and_id-$or_id";
my $field = $params->{"field$identifier"};
my $operator = $params->{"type$identifier"};
my $value = $params->{"value$identifier"};
return if (!defined $field or !defined $operator or !defined $value); return if (!defined $field or !defined $operator or !defined $value);
my $string_value; my $string_value;
if (ref $value eq 'ARRAY') { if (ref $value eq 'ARRAY') {
# Trim input and ignore blank values. # Trim input and ignore blank values.
...@@ -1626,15 +1573,14 @@ sub _handle_chart { ...@@ -1626,15 +1573,14 @@ sub _handle_chart {
# on multiple values, like anyexact. # on multiple values, like anyexact.
my %search_args = ( my %search_args = (
chart_id => $sql_chart_id, chart_id => $chart_id,
sequence => $or_id, sequence => $chart_id,
field => $field, field => $field,
full_field => $full_field, full_field => $full_field,
operator => $operator, operator => $operator,
value => $string_value, value => $string_value,
all_values => $value, all_values => $value,
joins => [], joins => [],
having => [],
); );
$search_args{quoted} = $self->_quote_unless_numeric(\%search_args); $search_args{quoted} = $self->_quote_unless_numeric(\%search_args);
# This should add a "term" selement to %search_args. # This should add a "term" selement to %search_args.
...@@ -1648,7 +1594,7 @@ sub _handle_chart { ...@@ -1648,7 +1594,7 @@ sub _handle_chart {
value => $string_value, term => $search_args{term}, value => $string_value, term => $search_args{term},
}); });
return \%search_args; $condition->translated(\%search_args);
} }
################################## ##################################
......
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is BugzillaSource, Inc.
# Portions created by the Initial Developer are Copyright (C) 2011 the
# Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Max Kanat-Alexander <mkanat@bugzilla.org>
package Bugzilla::Search::Clause;
use strict;
use Bugzilla::Search::Condition qw(condition);
sub new {
my ($class, $joiner) = @_;
bless { joiner => $joiner || 'AND' }, $class;
}
sub children {
my ($self) = @_;
$self->{children} ||= [];
return $self->{children};
}
sub joiner { return $_[0]->{joiner} }
sub has_children {
my ($self) = @_;
return scalar(@{ $self->children }) > 0 ? 1 : 0;
}
sub has_conditions {
my ($self) = @_;
my $children = $self->children;
return 1 if grep { $_->isa('Bugzilla::Search::Condition') } @$children;
foreach my $child (@$children) {
return 1 if $child->has_conditions;
}
return 0;
}
sub add {
my $self = shift;
my $children = $self->children;
if (@_ == 3) {
push(@$children, condition(@_));
return;
}
my ($child) = @_;
return if !defined $child;
$child->isa(__PACKAGE__) || $child->isa('Bugzilla::Search::Condition')
|| die 'child not the right type: ' . $child;
push(@{ $self->children }, $child);
}
sub negate {
my ($self, $value) = @_;
if (@_ == 2) {
$self->{negate} = $value;
}
return $self->{negate};
}
sub walk_conditions {
my ($self, $callback) = @_;
foreach my $child (@{ $self->children }) {
if ($child->isa('Bugzilla::Search::Condition')) {
$callback->($child);
}
else {
$child->walk_conditions($callback);
}
}
}
sub as_string {
my ($self) = @_;
my @strings;
foreach my $child (@{ $self->children }) {
next if $child->isa(__PACKAGE__) && !$child->has_conditions;
next if $child->isa('Bugzilla::Search::Condition')
&& !$child->translated;
my $string = $child->as_string;
if ($self->joiner eq 'AND') {
$string = "( $string )" if $string =~ /OR/;
}
else {
$string = "( $string )" if $string =~ /AND/;
}
push(@strings, $string);
}
my $sql = join(' ' . $self->joiner . ' ', @strings);
$sql = "NOT( $sql )" if $sql && $self->negate;
return $sql;
}
1;
\ No newline at end of file
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is BugzillaSource, Inc.
# Portions created by the Initial Developer are Copyright (C) 2011 the
# Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Max Kanat-Alexander <mkanat@bugzilla.org>
package Bugzilla::Search::Condition;
use strict;
use base qw(Exporter);
our @EXPORT_OK = qw(condition);
sub new {
my ($class, $params) = @_;
my %self = %$params;
bless \%self, $class;
return \%self;
}
sub field { return $_[0]->{field} }
sub operator { return $_[0]->{operator} }
sub value { return $_[0]->{value} }
sub fov {
my ($self) = @_;
return ($self->field, $self->operator, $self->value);
}
sub translated {
my ($self, $params) = @_;
if (@_ == 2) {
$self->{translated} = $params;
}
return $self->{translated};
}
sub as_string {
my ($self) = @_;
return $self->translated->{term};
}
###########################
# Convenience Subroutines #
###########################
sub condition {
my ($field, $operator, $value) = @_;
return __PACKAGE__->new({ field => $field, operator => $operator,
value => $value });
}
1;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment