Use same buglist generation code in whine.pl and in buglist.cgi

classes
Vitaliy Filippov 2015-12-29 17:03:51 +03:00
parent b37cc0c1b3
commit cedb870a81
6 changed files with 236 additions and 293 deletions

View File

@ -768,7 +768,6 @@ sub COLUMNS
sub REPORT_COLUMNS
{
my ($self, $user) = @_;
my ($user) = @_;
$user ||= Bugzilla->user;
my $cache = Bugzilla->request_cache;
return $cache->{report_columns}->{$user->id || ''} if $cache->{report_columns} && $cache->{report_columns}->{$user->id || ''};
@ -1570,6 +1569,146 @@ sub init
$self->{sql} = $query;
}
sub get_columns
{
my $class = shift;
my ($params, $user) = @_;
my $displaycolumns;
if (defined $params->{columnlist} && $params->{columnlist} ne 'all')
{
$displaycolumns = [ split(/[ ,]+/, $params->{columnlist}) ];
}
elsif (defined Bugzilla->cookies->{COLUMNLIST})
{
$displaycolumns = [ split(/ /, Bugzilla->cookies->{COLUMNLIST}) ];
}
else
{
# Use the default list of columns.
$displaycolumns = [ DEFAULT_COLUMN_LIST ];
}
# Figure out whether or not the user is doing a fulltext search. If not,
# we'll remove the relevance column from the lists of columns to display
# and order by, since relevance only exists when doing a fulltext search.
my $fulltext = $params->{content} ||
grep { $params->{$_} eq 'content' && /^field(\d+-\d+-\d+)/ && $params->{"value$1"} } keys %$params;
my $columns = $class->COLUMNS($user);
$_ = $class->COLUMN_ALIASES->{$_} || $_ for @$displaycolumns;
@$displaycolumns = grep($columns->{$_} && trick_taint($_), @$displaycolumns);
if (!$user->is_timetracker)
{
@$displaycolumns = grep { !TIMETRACKING_FIELDS->{$_} } @$displaycolumns;
}
# Remove the relevance column if the user is not doing a fulltext search.
if (grep('relevance', @$displaycolumns) && !$fulltext)
{
@$displaycolumns = grep($_ ne 'relevance', @$displaycolumns);
}
@$displaycolumns = grep($_ ne 'bug_id', @$displaycolumns);
# The bug ID is always selected because bug IDs are always displayed.
# Severity, priority, resolution and status are required for buglist
# CSS classes.
# Display columns are selected because otherwise we could not display them.
my $selectcolumns = { map { $_ => 1 } (qw(bug_id bug_severity priority bug_status resolution product), @$displaycolumns) };
# Make sure that the login_name version of a field is always also
# requested if the realname version is requested, so that we can
# display the login name when the realname is empty.
my @realname_fields = grep(/_realname$|_short$/, @$displaycolumns);
foreach my $item (@realname_fields)
{
my $login_field = $item;
$login_field =~ s/_realname$|_short$//;
$selectcolumns->{$login_field} = 1;
}
return ($displaycolumns, [ keys %$selectcolumns ]);
}
sub get_order
{
my $class = shift;
my ($params, $user) = @_;
my $order = $params->{order} || "";
# First check if we'll want to reuse the last sorting order; that happens if
# the order is not defined or its value is "reuse last sort"
if (!$order || $order =~ /^reuse/i)
{
if ($order = Bugzilla->cookies->{LASTORDER})
{
# Cookies from early versions of Specific Search included this text,
# which is now invalid.
$order =~ s/ LIMIT 200//;
}
else
{
$order = ''; # Remove possible "reuse" identifier as unnecessary
}
}
my $columns = $class->COLUMNS($user);
my $fulltext = $params->{content} ||
grep { $params->{$_} eq 'content' && /^field(\d+-\d+-\d+)/ && $params->{"value$1"} } keys %$params;
my $old_orders = {
'' => 'bug_status,priority,assigned_to,bug_id', # Default
'bug number' => 'bug_id',
'importance' => 'priority,bug_severity,bug_id',
'assignee' => 'assigned_to,bug_status,priority,bug_id',
'last changed' => 'delta_ts,bug_status,priority,assigned_to,bug_id',
};
my @invalid_fragments;
my @orderstrings;
if ($order)
{
# Convert the value of the "order" form field into a list of columns
# by which to sort the results.
if ($old_orders->{lc $order})
{
@orderstrings = split /,/, $old_orders->{lc $order};
}
else
{
trick_taint($order);
# A custom list of columns. Make sure each column is valid.
foreach my $fragment (split(/,/, $order))
{
$fragment = trim($fragment);
next unless $fragment;
my ($column_name, $direction) = Bugzilla::Search::split_order_term($fragment);
$column_name = Bugzilla::Search::translate_old_column($column_name);
# Special handlings for certain columns
next if $column_name eq 'relevance' && !$fulltext;
# If we are sorting by votes, sort in descending order if
# no explicit sort order was given.
if ($column_name eq 'votes' && !$direction)
{
$direction = "DESC";
}
if (exists $columns->{$column_name})
{
$direction = " $direction" if $direction;
push @orderstrings, "$column_name$direction";
}
else
{
push @invalid_fragments, $fragment;
}
}
}
}
$order = $old_orders->{''} if !$order;
return (\@orderstrings, \@invalid_fragments);
}
# Return query-wide equality operators
sub get_equalities
{

View File

@ -203,8 +203,6 @@ my $serverpush =
&& !defined($ARGS->{serverpush})
|| $ARGS->{serverpush};
my $order = $ARGS->{order} || "";
# The params object to use for the actual query itself
my $params;
@ -213,36 +211,17 @@ my $params;
if (defined $ARGS->{regetlastlist})
{
my $bug_id = Bugzilla->cookies->{BUGLIST} || ThrowUserError('missing_cookie');
$order = 'reuse last sort' unless $order;
$ARGS->{order} ||= 'reuse last sort';
$bug_id =~ s/:/,/g;
# set up the params for this new query
$params = {
bug_id => $bug_id,
bug_id_type => 'anyexact',
order => $order,
order => $ARGS->{order},
columnlist => $ARGS->{columnlist},
};
}
# Figure out whether or not the user is doing a fulltext search. If not,
# we'll remove the relevance column from the lists of columns to display
# and order by, since relevance only exists when doing a fulltext search.
my $fulltext = 0;
if ($ARGS->{content})
{
$fulltext = 1;
}
my @charts = map(/^field(\d-\d-\d)$/ ? $1 : (), keys %$ARGS);
foreach my $chart (@charts)
{
if ($ARGS->{"field$chart"} eq 'content' && $ARGS->{"value$chart"})
{
$fulltext = 1;
last;
}
}
################################################################################
# Utilities
################################################################################
@ -458,14 +437,12 @@ if ($cmdtype eq "dorem")
$vars->{search_id} = $query->id;
}
$params = http_decode_query($query->query.'&sharer_id='.$query->userid);
$order = $params->{order} || $order;
}
elsif ($remaction eq "runseries")
{
$vars->{searchname} = $ARGS->{namedcmd};
$vars->{searchtype} = "series";
$params = http_decode_query(LookupSeries($ARGS->{"series_id"}));
$order = $params->{order} || $order;
}
elsif ($remaction eq 'forget')
{
@ -524,117 +501,38 @@ elsif (($cmdtype eq 'doit') && defined $ARGS->{remtype})
}
}
################################################################################
# Column Definition
################################################################################
my $columns = Bugzilla::Search->COLUMNS;
################################################################################
# Display Column Determination
################################################################################
# Determine the columns that will be displayed in the bug list via the
# columnlist CGI parameter, the user's preferences, or the default.
my @displaycolumns = ();
if (defined $params->{columnlist} && $params->{columnlist} ne 'all')
{
@displaycolumns = split(/[ ,]+/, $params->{columnlist});
}
elsif (defined Bugzilla->cookies->{COLUMNLIST})
{
@displaycolumns = split(/ /, Bugzilla->cookies->{COLUMNLIST});
}
else
{
# Use the default list of columns.
@displaycolumns = DEFAULT_COLUMN_LIST;
}
$_ = Bugzilla::Search->COLUMN_ALIASES->{$_} || $_ for @displaycolumns;
# Weed out columns that don't actually exist to prevent the user
# from hacking their column list cookie to grab data to which they
# should not have access. Detaint the data along the way.
@displaycolumns = grep($columns->{$_} && trick_taint($_), @displaycolumns);
my ($displaycolumns, $selectcolumns) = Bugzilla::Search->get_columns($params, Bugzilla->user);
# Add the votes column to the list of columns to be displayed
# in the bug list if the user is searching for bugs with a certain
# number of votes and the votes column is not already on the list.
# Some versions of perl will taint 'votes' if this is done as a single
# statement, because the votes param is tainted at this point
my $votes = $params->{votes};
$votes ||= "";
if (trim($votes) && !grep($_ eq 'votes', @displaycolumns))
if (trim($params->{votes} || '') && !grep($_ eq 'votes', @$selectcolumns))
{
push(@displaycolumns, 'votes');
push @$displaycolumns, 'votes';
push @$selectcolumns, 'votes';
}
# Remove the timetracking columns if they are not a part of the group
# (happens if a user had access to time tracking and it was revoked/disabled)
if (!Bugzilla->user->is_timetracker)
if ($superworktime && !grep($_ eq 'interval_time', @$selectcolumns))
{
@displaycolumns = grep { !TIMETRACKING_FIELDS->{$_} } @displaycolumns;
}
# Remove the relevance column if the user is not doing a fulltext search.
if (grep('relevance', @displaycolumns) && !$fulltext)
{
@displaycolumns = grep($_ ne 'relevance', @displaycolumns);
}
# Remove the "ID" column from the list because bug IDs are always displayed
# and are hard-coded into the display templates.
@displaycolumns = grep($_ ne 'bug_id', @displaycolumns);
if ($superworktime && !grep($_ eq 'interval_time', @displaycolumns))
{
push @displaycolumns, 'interval_time';
}
################################################################################
# Select Column Determination
################################################################################
# Generate the list of columns that will be selected in the SQL query.
# The bug ID is always selected because bug IDs are always displayed.
# Severity, priority, resolution and status are required for buglist
# CSS classes.
my @selectcolumns = ("bug_id", "bug_severity", "priority", "bug_status", "resolution", "product");
# Make sure that the login_name version of a field is always also
# requested if the realname version is requested, so that we can
# display the login name when the realname is empty.
my @realname_fields = grep(/_realname$|_short$/, @displaycolumns);
foreach my $item (@realname_fields)
{
my $login_field = $item;
$login_field =~ s/_realname$|_short$//;
if (!grep($_ eq $login_field, @selectcolumns))
{
push(@selectcolumns, $login_field);
}
}
# Display columns are selected because otherwise we could not display them.
foreach my $col (@displaycolumns)
{
push (@selectcolumns, $col) if !grep($_ eq $col, @selectcolumns);
push @$displaycolumns, 'interval_time';
push @$selectcolumns, 'interval_time';
}
# If the user is editing multiple bugs, we also make sure to select the
# status, because the values of that field determines what options the user
# has for modifying the bugs.
if ($dotweak)
if ($dotweak && !grep($_ eq 'bug_status', @$selectcolumns))
{
push(@selectcolumns, "bug_status") if !grep($_ eq 'bug_status', @selectcolumns);
push @$selectcolumns, "bug_status";
}
if ($format->{extension} eq 'ics')
if ($format->{extension} eq 'ics' && !grep($_ eq 'creation_ts', @$selectcolumns))
{
push(@selectcolumns, "creation_ts") if !grep($_ eq 'creation_ts', @selectcolumns);
push @$selectcolumns, "creation_ts";
}
if ($format->{extension} eq 'atom')
@ -662,102 +560,26 @@ if ($format->{extension} eq 'atom')
foreach my $required (@required_atom_columns)
{
push(@selectcolumns, $required) if !grep($_ eq $required,@selectcolumns);
push(@$selectcolumns, $required) if !grep($_ eq $required, @$selectcolumns);
}
}
if ($superworktime && !grep($_ eq 'product_notimetracking', @displaycolumns))
if ($superworktime && !grep($_ eq 'product_notimetracking', @$displaycolumns))
{
push @selectcolumns, 'product_notimetracking';
push @$selectcolumns, 'product_notimetracking';
}
################################################################################
# Sort Order Determination
################################################################################
# Add to the query some instructions for sorting the bug list.
# First check if we'll want to reuse the last sorting order; that happens if
# the order is not defined or its value is "reuse last sort"
if (!$order || $order =~ /^reuse/i)
my ($orderstrings, $invalid_fragments) = Bugzilla::Search->get_order($params, Bugzilla->user);
if (scalar @$invalid_fragments)
{
if ($order = Bugzilla->cookies->{LASTORDER})
{
# Cookies from early versions of Specific Search included this text,
# which is now invalid.
$order =~ s/ LIMIT 200//;
}
else
{
$order = ''; # Remove possible "reuse" identifier as unnecessary
}
$vars->{message} = 'invalid_column_name';
$vars->{invalid_fragments} = $invalid_fragments;
}
# FIXME Move sort orders to Bugzilla::Search
my $old_orders = {
'' => 'bug_status,priority,assigned_to,bug_id', # Default
'bug number' => 'bug_id',
'importance' => 'priority,bug_severity,bug_id',
'assignee' => 'assigned_to,bug_status,priority,bug_id',
'last changed' => 'delta_ts,bug_status,priority,assigned_to,bug_id',
};
if ($order)
{
# Convert the value of the "order" form field into a list of columns
# by which to sort the results.
if ($old_orders->{lc $order})
{
$order = $old_orders->{lc $order};
}
else
{
my (@order, @invalid_fragments);
# A custom list of columns. Make sure each column is valid.
foreach my $fragment (split(/,/, $order))
{
$fragment = trim($fragment);
next unless $fragment;
my ($column_name, $direction) = Bugzilla::Search::split_order_term($fragment);
$column_name = Bugzilla::Search::translate_old_column($column_name);
# Special handlings for certain columns
next if $column_name eq 'relevance' && !$fulltext;
# If we are sorting by votes, sort in descending order if
# no explicit sort order was given.
if ($column_name eq 'votes' && !$direction)
{
$direction = "DESC";
}
if (exists $columns->{$column_name})
{
$direction = " $direction" if $direction;
push @order, "$column_name$direction";
}
else
{
push @invalid_fragments, $fragment;
}
}
if (scalar @invalid_fragments)
{
$vars->{message} = 'invalid_column_name';
$vars->{invalid_fragments} = \@invalid_fragments;
}
$order = join(",", @order);
# Now that we have checked that all columns in the order are valid,
# detaint the order string.
trick_taint($order) if $order;
}
}
$order = $old_orders->{''} if !$order;
my @orderstrings = split(/,\s*/, $order);
# The bug status defined by a specific search is of type __foo__, but
# Search.pm converts it into a list of real bug statuses, which cannot
# be used when editing the specific search again. So we restore this
@ -770,9 +592,9 @@ if ($query_format eq 'specific')
# Generate the basic SQL query that will be used to generate the bug list.
my $search = new Bugzilla::Search(
'fields' => \@selectcolumns,
'fields' => $selectcolumns,
'params' => $params,
'order' => \@orderstrings
'order' => $orderstrings,
);
my $query = $search->getSQL();
$vars->{search_description} = $search->search_description_html;
@ -798,12 +620,9 @@ if (defined $ARGS->{limit})
$query .= " " . $dbh->sql_limit($limit);
}
}
elsif ($fulltext)
elsif ($ARGS->{order} && $ARGS->{order} =~ /^relevance/)
{
if ($ARGS->{order} && $ARGS->{order} =~ /^relevance/)
{
$vars->{message} = 'buglist_sorted_by_relevance';
}
$vars->{message} = 'buglist_sorted_by_relevance';
}
if ($superworktime)
@ -899,11 +718,11 @@ $buglist_sth->execute();
# Retrieve the query results one row at a time and write the data into a list of Perl records.
# If we're doing time tracking, then keep totals for all bugs.
my $percentage_complete = 1 && grep { $_ eq 'percentage_complete' } @displaycolumns;
my $estimated_time = 1 && grep { $_ eq 'estimated_time' } @displaycolumns;
my $remaining_time = $percentage_complete || grep { $_ eq 'remaining_time' } @displaycolumns;
my $work_time = $percentage_complete || grep { $_ eq 'work_time' } @displaycolumns;
my $interval_time = $percentage_complete || grep { $_ eq 'interval_time' } @displaycolumns;
my $percentage_complete = 1 && grep { $_ eq 'percentage_complete' } @$displaycolumns;
my $estimated_time = 1 && grep { $_ eq 'estimated_time' } @$displaycolumns;
my $remaining_time = $percentage_complete || grep { $_ eq 'remaining_time' } @$displaycolumns;
my $work_time = $percentage_complete || grep { $_ eq 'work_time' } @$displaycolumns;
my $interval_time = $percentage_complete || grep { $_ eq 'interval_time' } @$displaycolumns;
my $time_info = {
estimated_time => 0,
@ -929,7 +748,7 @@ while (my @row = $buglist_sth->fetchrow_array())
# Slurp the row of data into the record.
# The second from last column in the record is the number of groups
# to which the bug is restricted.
foreach my $column (@selectcolumns)
foreach my $column (@$selectcolumns)
{
$bug->{$column} = shift @row;
}
@ -938,12 +757,6 @@ while (my @row = $buglist_sth->fetchrow_array())
if ($bug->{delta_ts})
{
$bug->{delta_ts} =~ s/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/$1-$2-$3 $4:$5:$6/;
$bug->{delta_ts_diff} = DiffDate($bug->{delta_ts});
}
if ($bug->{creation_ts})
{
$bug->{creation_ts_diff} = DiffDate($bug->{creation_ts});
}
# Record the assignee, product, and status in the big hashes of those things.
@ -1023,7 +836,7 @@ else
$vars->{bugs} = \@bugs;
$vars->{buglist} = \@bugidlist;
$vars->{buglist_joined} = join(',', @bugidlist);
$vars->{displaycolumns} = \@displaycolumns;
$vars->{displaycolumns} = $displaycolumns;
$vars->{openstates} = [ map { $_->name } grep { $_->is_open } Bugzilla::Status->get_all ];
# used by list.ics.tmpl
@ -1069,8 +882,8 @@ if ($vars->{urlquerypart}->{sharer_id})
}
$vars->{urlquerypart} = http_build_query($vars->{urlquerypart});
$vars->{rssquerypart} = $vars->{urlquerypart};
$vars->{order} = $order;
$vars->{order_columns} = [ @orderstrings ];
$vars->{order} = $params->{order};
$vars->{order_columns} = $orderstrings;
$vars->{order_dir} = [ map { s/ DESC$// ? 1 : 0 } @{$vars->{order_columns}} ];
$vars->{caneditbugs} = 1;
@ -1290,11 +1103,11 @@ my $disposition = "inline";
if ($format->{extension} eq "html" && !$agent)
{
if ($order && !$ARGS->{sharer_id} && $query_format ne 'specific')
if ($ARGS->{order} && !$ARGS->{sharer_id} && $query_format ne 'specific')
{
$cgi->send_cookie(
-name => 'LASTORDER',
-value => $order,
-value => $ARGS->{order},
-expires => 'Fri, 01-Jan-2038 00:00:00 GMT'
);
}

View File

@ -24,10 +24,10 @@
text-decoration: none;
}
th.sorttable_sorted a:after { content: "▲"; color: gray; }
th.sorttable_sorted_reverse a:after { content: "▼"; color: gray; }
th.sorted_0.sorttable_sorted a:after { content: "▲"; color: black; }
th.sorted_0.sorttable_sorted_reverse a:after { content: "▼"; color: black; }
th.sorttable_sorted a:after { content: "\25B2";/*▲*/ color: gray; }
th.sorttable_sorted_reverse a:after { content: "\25BC";/*▼*/ color: gray; }
th.sorted_0.sorttable_sorted a:after { content: "\25B2";/*▲*/ color: black; }
th.sorted_0.sorttable_sorted_reverse a:after { content: "\25BC";/*▼*/ color: black; }
th.sorted_0 { background-color: #a0a0a0; }
th.sorted_1 { background-color: #acacac; }
th.sorted_2 { background-color: #b8b8b8; }

View File

@ -263,7 +263,7 @@
[%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]
</a>
[% ELSIF column == 'bug_file_loc' && bug.$column.search('http:') %]
<a href="[%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]" target="_blank">
<a href="[%- bug.$column FILTER html -%]" target="_blank">
[%- bug.$column.truncate(abbrev.$column.maxlength, abbrev.$column.ellipsis) FILTER html -%]
</a>
[% ELSE %]

View File

@ -34,56 +34,41 @@
<title>
[[% terms.Bugzilla %]] [% subject FILTER html %]
</title>
<style>
[% style | none %]
</style>
</head>
<body bgcolor="#FFFFFF">
<p align="left">
[% body FILTER html %]
</p>
<p align="left">
[% body FILTER html %]
</p>
<p align="left">
[% IF author.login == recipient.login %]
<a href="[%+ urlbase FILTER html %]editwhines.cgi">Click
here to edit your whine schedule</a>
[% ELSE %]
This search was scheduled by [% author.login FILTER html %].
[% END %]
</p>
<p align="left">
[% IF author.login == recipient.login %]
<a href="[%+ urlbase FILTER html %]editwhines.cgi">Click
here to edit your whine schedule</a>
[% ELSE %]
This search was scheduled by [% author.login FILTER html %].
[% END %]
</p>
[% FOREACH query=queries %]
[% FOREACH query=queries %]
<h2>[%+ query.title FILTER html %]</h2>
<table width="100%">
<tr>
<th align="left">ID</th>
<th align="left">Sev</th>
<th align="left">Pri</th>
<th align="left">Plt</th>
<th align="left">Assignee</th>
<th align="left">Status</th>
<th align="left">Resolution</th>
<th align="left">Summary</th>
</tr>
[% code = BLOCK %]
[% PROCESS "list/table.html.tmpl"
bugs = query.bugs
order_columns = query.order_columns
order = query.order_columns.join(',')
displaycolumns = query.displaycolumns
template_format = 'simple'
%]
[% END %]
[% code.replace('<a href="([a-z_]+)\.cgi', '<a href="' _ urlbase _ '$1.cgi') | none %]
[% FOREACH bug=query.bugs %]
<tr>
<td align="left"><a href="[%+ urlbase FILTER html %]show_bug.cgi?id=
[%- bug.bug_id %]">[% bug.bug_id %]</a></td>
<td align="left">[% bug.bug_severity_obj.name FILTER html %]</td>
<td align="left">[% bug.priority_obj.name FILTER html %]</td>
<td align="left">[% bug.rep_platform_obj.name FILTER html %]</td>
<td align="left">[% bug.assigned_to FILTER html %]</td>
<td align="left">[% bug.bug_status_obj.name FILTER html %]</td>
<td align="left">[% bug.resolution_obj.name FILTER html %]</td>
<td align="left">[% bug.short_desc FILTER html %]</td>
</tr>
[% END %]
</table>
[% END %]
[% END %]
</body>
</html>

View File

@ -323,6 +323,13 @@ sub mail
my $template = Bugzilla->template_inner($addressee->settings->{lang}->{value});
my $msg = ''; # it's a temporary variable to hold the template output
$args->{alternatives} ||= [];
$args->{style} = '';
if (open my $fd, bz_locations()->{skinsdir}.'/standard/buglist.css')
{
local $/ = undef;
$args->{style} = <$fd>;
close $fd;
}
# put together the different multipart mime segments
@ -367,51 +374,50 @@ sub run_queries
my $queries = $dbh->selectall_arrayref(
"SELECT query_name, title, onemailperbug FROM whine_queries".
" WHERE eventid=? ORDER BY sortkey", {Slice=>{}}
" WHERE eventid=? ORDER BY sortkey", {Slice=>{}}, $args->{eventid}
);
foreach my $thisquery (@$queries)
{
$thisquery->{bugs} = [];
next unless $thisquery->{name}; # named query is blank
next unless $thisquery->{query_name}; # named query is blank
my $savedquery = Bugzilla::Search::Saved->new({ name => $thisquery->{name}, user => $args->{author} });
my $savedquery = Bugzilla::Search::Saved->new({ name => $thisquery->{query_name}, user => $args->{author} });
next unless $savedquery; # silently ignore missing queries
# Execute the saved query
my @searchfields = qw(
bug_id
bug_severity
priority
rep_platform
assigned_to
bug_status
resolution
short_desc
);
my $params = http_decode_query($savedquery->query);
my ($displaycolumns, $selectcolumns) = Bugzilla::Search->get_columns($params, $args->{recipient});
my ($orderstrings) = Bugzilla::Search->get_order($params, $args->{recipient});
my $search = new Bugzilla::Search(
fields => \@searchfields,
params => http_decode_query($savedquery->query),
fields => $selectcolumns,
params => $params,
user => $args->{recipient}, # the search runs as the recipient
order => $orderstrings,
);
my $sqlquery = $search->getSQL();
my $sth = $dbh->prepare($sqlquery);
$sth->execute;
$thisquery->{order_columns} = $orderstrings;
$thisquery->{displaycolumns} = $displaycolumns;
$thisquery->{bugs} = [];
while (my @row = $sth->fetchrow_array)
{
my $bug = {};
for my $field (@searchfields)
for my $column (@$selectcolumns)
{
my $fieldname = $field;
$fieldname =~ s/^bugs\.//; # No need for bugs.whatever
$bug->{$fieldname} = shift @row;
$bug->{$column} = shift @row;
}
# Process certain values further (i.e. date format conversion).
if ($bug->{delta_ts})
{
$bug->{delta_ts} =~ s/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/$1-$2-$3 $4:$5:$6/;
}
if ($thisquery->{onemailperbug})
{
$args->{queries} = [ {
name => $thisquery->{name},
title => $thisquery->{title},
bugs => [ $bug ],
%$thisquery,
bugs => [ $bug ],
} ];
mail($args);
delete $args->{queries};
@ -424,7 +430,7 @@ sub run_queries
}
if (!$thisquery->{onemailperbug} && @{$thisquery->{bugs}})
{
push @{$return_queries}, $thisquery;
push @$return_queries, $thisquery;
}
}