Mostly remove bug_status hardcode, fix some more SQL queries for new schema

master
Vitaliy Filippov 2014-04-14 18:42:55 +04:00
parent e1b83084a1
commit 08136a9c69
35 changed files with 217 additions and 228 deletions

View File

@ -2855,7 +2855,7 @@ sub statuses_available
} }
# *Only* users with (product-specific) "canconfirm" privs can confirm bugs. # *Only* users with (product-specific) "canconfirm" privs can confirm bugs.
if (!$self->status->is_confirmed && !$user->in_group('canconfirm', $self->product_id)) if (!$self->status->is_confirmed && !Bugzilla->user->in_group('canconfirm', $self->product_id))
{ {
@statuses = grep { !$_->is_confirmed } @statuses; @statuses = grep { !$_->is_confirmed } @statuses;
} }

View File

@ -1431,7 +1431,7 @@ Bugzilla::DB - Database access routines, using L<DBI>
# prepare a query using DB methods # prepare a query using DB methods
my $sth = $dbh->prepare("SELECT " . my $sth = $dbh->prepare("SELECT " .
$dbh->sql_date_format("creation_ts", "%Y%m%d") . $dbh->sql_date_format("creation_ts", "%Y%m%d") .
" FROM bugs WHERE bug_status != 'RESOLVED' " . " FROM bugs WHERE bug_status != 4 " .
$dbh->sql_limit(1)); $dbh->sql_limit(1));
# Execute the query # Execute the query

View File

@ -157,17 +157,6 @@ sub update
if (exists $changes->{$self->NAME_FIELD}) if (exists $changes->{$self->NAME_FIELD})
{ {
my ($old, $new) = @{ $changes->{$self->NAME_FIELD} }; my ($old, $new) = @{ $changes->{$self->NAME_FIELD} };
if ($self->field->type != FIELD_TYPE_MULTI_SELECT)
{
$self->field->{has_activity} = 1;
$dbh->do(
"INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, added, removed)".
" SELECT bug_id, ?, NOW(), ?, ?, ? FROM bugs WHERE $fname = ?", undef,
Bugzilla->user->id, $self->field->id, $new, $old, $old
);
$dbh->do("UPDATE bugs SET $fname = ?, lastdiffed = NOW() WHERE $fname = ?",
undef, $new, $old);
}
if ($old_self->is_default) if ($old_self->is_default)
{ {
my $param = $self->DEFAULT_MAP->{$self->field->name}; my $param = $self->DEFAULT_MAP->{$self->field->name};

View File

@ -715,6 +715,12 @@ WHERE description LIKE\'%[CC:%\'');
$dbh->bz_add_fk('bugs', $_->name, { TABLE => 'bugs', COLUMN => 'bug_id' }); $dbh->bz_add_fk('bugs', $_->name, { TABLE => 'bugs', COLUMN => 'bug_id' });
} }
# Add is_assigned and is_confirmed columns to bug_status table
$dbh->bz_add_column('bug_status', is_assigned => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'});
$dbh->bz_add_column('bug_status', is_confirmed => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE'});
$dbh->do('UPDATE bug_status SET is_assigned=0 WHERE NOT value=?', undef, 'ASSIGNED');
$dbh->do('UPDATE bug_status SET is_confirmed=0 WHERE value=?', undef, 'UNCONFIRMED');
################################################################ ################################################################
# New --TABLE-- changes should go *** A B O V E *** this point # # New --TABLE-- changes should go *** A B O V E *** this point #
################################################################ ################################################################

View File

@ -128,30 +128,8 @@ sub update
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction(); $dbh->bz_start_transaction();
# Not Bugzilla::Field::Choice! It will overwrite other products' bug values
my ($changes, $old_self) = Bugzilla::Object::update($self, @_); my ($changes, $old_self) = Bugzilla::Object::update($self, @_);
if (exists $changes->{value})
{
# Record activity
$self->field->{has_activity} = 1;
$dbh->do(
'INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, added, removed)'.
' SELECT bug_id, ?, NOW(), ?, ?, ? FROM bugs WHERE target_milestone = ? AND product_id = ?', undef,
Bugzilla->user->id, $self->field->id, $self->name, $changes->{value}->[0], $changes->{value}->[0], $self->product_id
);
# The milestone value is stored in the bugs table instead of its ID.
$dbh->do(
'UPDATE bugs SET target_milestone = ?, lastdiffed = NOW() WHERE target_milestone = ? AND product_id = ?',
undef, $self->name, $changes->{value}->[0], $self->product_id
);
# The default milestone also stores the value instead of the ID.
$dbh->do(
'UPDATE products SET defaultmilestone = ? WHERE id = ? AND defaultmilestone = ?',
undef, $self->name, $self->product_id, $changes->{value}->[0]
);
}
# Fill visibility values # Fill visibility values
$self->set_visibility_values([ $self->product_id ]); $self->set_visibility_values([ $self->product_id ]);
@ -162,36 +140,41 @@ sub update
return $changes; return $changes;
} }
sub remove_from_db { sub remove_from_db
{
my $self = shift; my $self = shift;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
# The default milestone cannot be deleted. # The default milestone cannot be deleted.
if ($self->name eq $self->product->default_milestone) { if ($self->id eq $self->product->default_milestone)
{
ThrowUserError('milestone_is_default', { milestone => $self }); ThrowUserError('milestone_is_default', { milestone => $self });
} }
if ($self->bug_count) { if ($self->bug_count)
{
# We don't want to delete bugs when deleting a milestone. # We don't want to delete bugs when deleting a milestone.
# Bugs concerned are reassigned to the default milestone. # Bugs concerned are reassigned to the default milestone.
my $bug_ids = my $bug_ids = $dbh->selectcol_arrayref(
$dbh->selectcol_arrayref('SELECT bug_id FROM bugs 'SELECT bug_id FROM bugs WHERE product_id = ? AND target_milestone = ?',
WHERE product_id = ? AND target_milestone = ?', undef, ($self->product->id, $self->id)
undef, ($self->product->id, $self->name)); );
my $timestamp = $dbh->selectrow_array('SELECT NOW()'); my $timestamp = $dbh->selectrow_array('SELECT NOW()');
$dbh->do('UPDATE bugs SET target_milestone = ?, delta_ts = ? $dbh->do(
WHERE ' . $dbh->sql_in('bug_id', $bug_ids), 'UPDATE bugs SET target_milestone = ?, delta_ts = ? WHERE ' . $dbh->sql_in('bug_id', $bug_ids),
undef, ($self->product->default_milestone, $timestamp)); undef, ($self->product->default_milestone, $timestamp)
);
require Bugzilla::Bug; require Bugzilla::Bug;
import Bugzilla::Bug qw(LogActivityEntry); my $def = Bugzilla::Milestone->new($self->product->default_milestone);
foreach my $bug_id (@$bug_ids) { foreach my $bug_id (@$bug_ids)
LogActivityEntry($bug_id, 'target_milestone', {
$self->name, Bugzilla::Bug::LogActivityEntry(
$self->product->default_milestone, $bug_id, 'target_milestone', $self->name,
Bugzilla->user->id, $timestamp); $def && $def->name, Bugzilla->user->id, $timestamp
);
} }
} }
@ -249,17 +232,19 @@ sub _check_product {
sub set_name { $_[0]->set('value', $_[1]); } sub set_name { $_[0]->set('value', $_[1]); }
sub set_sortkey { $_[0]->set('sortkey', $_[1]); } sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
sub bug_count { sub bug_count
{
my $self = shift; my $self = shift;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
if (!defined $self->{'bug_count'}) { if (!defined $self->{bug_count})
$self->{'bug_count'} = $dbh->selectrow_array(q{ {
SELECT COUNT(*) FROM bugs $self->{bug_count} = $dbh->selectrow_array(
WHERE product_id = ? AND target_milestone = ?}, "SELECT COUNT(*) FROM bugs WHERE product_id = ? AND target_milestone = ?",
undef, $self->product_id, $self->name) || 0; undef, $self->product_id, $self->id
) || 0;
} }
return $self->{'bug_count'}; return $self->{bug_count};
} }
################################ ################################

View File

@ -1,5 +1,3 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public # The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file # License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of # except in compliance with the License. You may obtain a copy of
@ -17,6 +15,8 @@
# Andreas Franke <afranke@mathweb.org> # Andreas Franke <afranke@mathweb.org>
# Stephen Lee <slee@uk.bnsmc.com> # Stephen Lee <slee@uk.bnsmc.com>
# Marc Schumann <wurblzap@gmail.com> # Marc Schumann <wurblzap@gmail.com>
#
# Refactoring by Vitaliy Filippov <vitalif@mail.ru>
package Bugzilla::Search::Quicksearch; package Bugzilla::Search::Quicksearch;

View File

@ -45,10 +45,15 @@ use constant SPECIAL_STATUS_WORKFLOW_ACTIONS => qw(
use constant DB_TABLE => 'bug_status'; use constant DB_TABLE => 'bug_status';
use constant FIELD_NAME => 'bug_status'; use constant FIELD_NAME => 'bug_status';
# This has all the standard Bugzilla::Field::Choice columns plus "is_open" # This has all the standard Bugzilla::Field::Choice columns plus some new ones
sub DB_COLUMNS sub DB_COLUMNS
{ {
return ($_[0]->SUPER::DB_COLUMNS, 'is_open'); return ($_[0]->SUPER::DB_COLUMNS, qw(is_open is_assigned is_confirmed));
}
sub UPDATE_COLUMNS
{
return ($_[0]->SUPER::UPDATE_COLUMNS, qw(is_open is_assigned is_confirmed));
} }
sub VALIDATORS sub VALIDATORS
@ -56,6 +61,8 @@ sub VALIDATORS
my $invocant = shift; my $invocant = shift;
my $validators = $invocant->SUPER::VALIDATORS; my $validators = $invocant->SUPER::VALIDATORS;
$validators->{is_open} = \&Bugzilla::Object::check_boolean; $validators->{is_open} = \&Bugzilla::Object::check_boolean;
$validators->{is_assigned} = \&Bugzilla::Object::check_boolean;
$validators->{is_confirmed} = \&Bugzilla::Object::check_boolean;
$validators->{value} = \&_check_value; $validators->{value} = \&_check_value;
return $validators; return $validators;
} }
@ -91,15 +98,13 @@ sub remove_from_db
sub is_active { return $_[0]->{isactive}; } sub is_active { return $_[0]->{isactive}; }
sub is_open { return $_[0]->{is_open}; } sub is_open { return $_[0]->{is_open}; }
sub is_assigned { return $_[0]->{is_assigned}; }
sub is_confirmed { return $_[0]->{is_confirmed}; }
sub is_static sub is_static
{ {
my $self = shift; my $self = shift;
if ($self->name eq 'UNCONFIRMED' || $self->name eq Bugzilla->params->{duplicate_or_move_bug_status}) return $self->name eq Bugzilla->params->{duplicate_or_move_bug_status} ? 1 : 0;
{
return 1;
}
return 0;
} }
############## ##############

View File

@ -936,8 +936,7 @@ sub create {
'user' => sub { return Bugzilla->user; }, 'user' => sub { return Bugzilla->user; },
# Currenly active language # Currenly active language
# XXX Eventually this should probably be replaced with something # FIXME Eventually this should probably be replaced with something like Bugzilla->language.
# like Bugzilla->language.
'current_language' => sub { 'current_language' => sub {
my ($language) = include_languages(); my ($language) = include_languages();
return $language; return $language;

View File

@ -1549,17 +1549,19 @@ sub wants_bug_mail {
$wants_mail &= $self->wants_mail([EVT_CHANGED_BY_ME], $relationship); $wants_mail &= $self->wants_mail([EVT_CHANGED_BY_ME], $relationship);
} }
if ($wants_mail) { if ($wants_mail)
{
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
# We don't create a Bug object from the bug_id here because we only # We don't create a Bug object from the bug_id here because we only
# need one piece of information, and doing so (as of 2004-11-23) slows # need one piece of information, and doing so (as of 2004-11-23) slows
# down bugmail sending by a factor of 2. If Bug creation was more # down bugmail sending by a factor of 2. If Bug creation was more
# lazy, this might not be so bad. # lazy, this might not be so bad.
my $bug_status = $dbh->selectrow_array('SELECT bug_status # FIXME: db abstraction?... or cache this value?...
FROM bugs WHERE bug_id = ?', my ($is_confirmed) = $dbh->selectrow_array(
undef, $bug_id); 'SELECT bs.is_confirmed FROM bugs b, bug_status bs WHERE b.bug_id=? AND bs.id=b.bug_status', undef, $bug_id
);
if ($bug_status eq "UNCONFIRMED") { if (!$is_confirmed)
{
$wants_mail &= $self->wants_mail([EVT_UNCONFIRMED], $relationship); $wants_mail &= $self->wants_mail([EVT_UNCONFIRMED], $relationship);
} }
} }

View File

@ -115,17 +115,18 @@ sub run_create_validators {
return $params; return $params;
} }
sub bug_count { sub bug_count
{
my $self = shift; my $self = shift;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
if (!defined $self->{bug_count})
if (!defined $self->{'bug_count'}) { {
$self->{'bug_count'} = $dbh->selectrow_array(qq{ $self->{bug_count} = $dbh->selectrow_array(
SELECT COUNT(*) FROM bugs "SELECT COUNT(*) FROM bugs WHERE product_id = ? AND version = ?",
WHERE product_id = ? AND version = ?}, undef, undef, ($self->product_id, $self->id)
($self->product_id, $self->name)) || 0; ) || 0;
} }
return $self->{'bug_count'}; return $self->{bug_count};
} }
sub create sub create
@ -149,25 +150,8 @@ sub update
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction(); $dbh->bz_start_transaction();
# Not Bugzilla::Field::Choice! It will overwrite other products' bug values
my ($changes, $old_self) = Bugzilla::Object::update($self, @_); my ($changes, $old_self) = Bugzilla::Object::update($self, @_);
if (exists $changes->{value})
{
# Record activity
$self->field->{has_activity} = 1;
$dbh->do(
'INSERT INTO bugs_activity (bug_id, who, bug_when, fieldid, added, removed)'.
' SELECT bug_id, ?, NOW(), ?, ?, ? FROM bugs WHERE version = ? AND product_id = ?', undef,
Bugzilla->user->id, $self->field->id, $self->name, $old_self->name, $old_self->name, $self->product_id
);
# Rename version
$dbh->do(
'UPDATE bugs SET version = ?, lastdiffed = NOW() WHERE version = ? AND product_id = ?',
undef, $self->name, $old_self->name, $self->product_id
);
}
# Fill visibility values # Fill visibility values
$self->set_visibility_values([ $self->product_id ]); $self->set_visibility_values([ $self->product_id ]);
@ -178,13 +162,13 @@ sub update
return $changes; return $changes;
} }
sub remove_from_db { sub remove_from_db
{
my $self = shift; my $self = shift;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
# The version cannot be removed if there are bugs associated with it.
# The version cannot be removed if there are bugs if ($self->bug_count)
# associated with it. {
if ($self->bug_count) {
ThrowUserError("version_has_bugs", { nb => $self->bug_count }); ThrowUserError("version_has_bugs", { nb => $self->bug_count });
} }
# Remove visibility values # Remove visibility values

View File

@ -1184,7 +1184,9 @@ $vars->{columns} = $columns;
$vars->{displaycolumns} = \@displaycolumns; $vars->{displaycolumns} = \@displaycolumns;
$vars->{openstates} = [BUG_STATE_OPEN]; $vars->{openstates} = [BUG_STATE_OPEN];
$vars->{closedstates} = [map {$_->name} closed_bug_statuses()]; # used by list.ics.tmpl
$vars->{assignedstates} = [ map { $_->name } grep { $_->is_active && $_->is_assigned } Bugzilla::Status->get_all ];
$vars->{closedstates} = [ map { $_->name } closed_bug_statuses() ];
# The iCal file needs priorities ordered from 1 to 9 (highest to lowest) # The iCal file needs priorities ordered from 1 to 9 (highest to lowest)
# If there are more than 9 values, just make all the lower ones 9 # If there are more than 9 values, just make all the lower ones 9

View File

@ -118,9 +118,9 @@ my @resolutions = @{$fields->{'resolution'}};
my (%bug_status, %bug_resolution, %removed); my (%bug_status, %bug_resolution, %removed);
if ($regenerate) { if ($regenerate) {
%bug_resolution = @{ $dbh->selectcol_arrayref( %bug_resolution = @{ $dbh->selectcol_arrayref(
'SELECT bug_id, resolution FROM bugs', {Columns=>[1,2]}) }; 'SELECT bug_id, resolution.value FROM bugs LEFT JOIN resolution ON resolution.id=bugs.resolution', {Columns=>[1,2]}) };
%bug_status = @{ $dbh->selectcol_arrayref( %bug_status = @{ $dbh->selectcol_arrayref(
'SELECT bug_id, bug_status FROM bugs', {Columns=>[1,2]}) }; 'SELECT bug_id, bug_status.value FROM bugs LEFT JOIN bug_status ON bug_status.id=bugs.bug_status', {Columns=>[1,2]}) };
my $removed_sth = $dbh->prepare( my $removed_sth = $dbh->prepare(
q{SELECT bugs_activity.bug_id, bugs_activity.removed,} q{SELECT bugs_activity.bug_id, bugs_activity.removed,}
@ -209,8 +209,8 @@ sub collect_stats {
# Now collect current data. # Now collect current data.
my @row = (today()); my @row = (today());
my $status_sql = q{SELECT COUNT(*) FROM bugs WHERE bug_status = ?}; my $status_sql = q{SELECT COUNT(*) FROM bugs, bug_status WHERE bugs.bug_status=bug_status.id AND bug_status.value = ?};
my $reso_sql = q{SELECT COUNT(*) FROM bugs WHERE resolution = ?}; my $reso_sql = q{SELECT COUNT(*) FROM bugs, resolution WHERE bugs.resolution=resolution.id AND resolution.value = ?};
if ($product ne '-All-') { if ($product ne '-All-') {
$status_sql .= q{ AND product_id = ?}; $status_sql .= q{ AND product_id = ?};

View File

@ -180,10 +180,11 @@ my %since_dups = @{$dbh->selectcol_arrayref(
"SELECT dupe_of, COUNT(dupe) "SELECT dupe_of, COUNT(dupe)
FROM duplicates INNER JOIN bugs_activity FROM duplicates INNER JOIN bugs_activity
ON bugs_activity.bug_id = duplicates.dupe ON bugs_activity.bug_id = duplicates.dupe
WHERE added = 'DUPLICATE' AND fieldid = ? WHERE added = ? AND fieldid = ?
AND bug_when >= LOCALTIMESTAMP(0) - " AND bug_when >= LOCALTIMESTAMP(0) - "
. $dbh->sql_interval('?', 'DAY') . . $dbh->sql_interval('?', 'DAY') .
" GROUP BY dupe_of", {Columns=>[1,2]}, " GROUP BY dupe_of", {Columns=>[1,2]},
Bugzilla->params->{duplicate_resolution},
$reso_field_id, $changedsince)}; $reso_field_id, $changedsince)};
add_indirect_dups(\%since_dups, \%dupe_relation); add_indirect_dups(\%since_dups, \%dupe_relation);

View File

@ -311,6 +311,7 @@ if ($action eq 'update') {
$vars->{'classification'} = new Bugzilla::Classification($product->classification_id); $vars->{'classification'} = new Bugzilla::Classification($product->classification_id);
} }
$vars->{'product'} = $product; $vars->{'product'} = $product;
$vars->{unconfirmed_states} = [ map { $_->name } grep { !$_->is_confirmed } Bugzilla::Status->get_all ];
$vars->{'changes'} = $changes; $vars->{'changes'} = $changes;
$template->process("admin/products/updated.html.tmpl", $vars) $template->process("admin/products/updated.html.tmpl", $vars)

View File

@ -212,20 +212,17 @@ if ($action eq 'update')
{ {
check_token_data($token, 'edit_field_value'); check_token_data($token, 'edit_field_value');
$vars->{value_old} = $value->name; $vars->{value_old} = $value->name;
if ($value->can('set_timetracking')) for ($value->UPDATE_COLUMNS)
{ {
$value->set_timetracking($ARGS->{timetracking} ? 1 : 0); if ($_ ne 'isactive' && $_ ne $value->NAME_FIELD || !$value->is_static && !$value->is_default)
}
$value->set_sortkey($ARGS->{sortkey});
if (!($value->is_static || $value->is_default))
{
$value->set_is_active($ARGS->{is_active});
$value->set_name($ARGS->{value_new});
if ($value->field->value_field)
{ {
$vars->{changes}->{visibility_values} = $value->set_visibility_values($ARGS->{visibility_value_id}); $value->set($_, $ARGS->{$_ eq $value->NAME_FIELD ? 'value_new' : $_});
} }
} }
if (!($value->is_static || $value->is_default) && $value->field->value_field)
{
$vars->{changes}->{visibility_values} = $value->set_visibility_values($ARGS->{visibility_value_id});
}
delete_token($token); delete_token($token);
$vars->{changes} = $value->update; $vars->{changes} = $value->update;
$vars->{message} = 'field_value_updated'; $vars->{message} = 'field_value_updated';

View File

@ -85,7 +85,7 @@ elsif ($action eq 'update') {
# Part 1: Initial bug statuses. # Part 1: Initial bug statuses.
foreach my $new (@$statuses) { foreach my $new (@$statuses) {
if (($new->is_open || $new->name eq 'RESOLVED') && $cgi->param('w_0_' . $new->id)) { if (($new->is_open || $new->name eq Bugzilla->params->{duplicate_or_move_bug_status}) && $cgi->param('w_0_' . $new->id)) {
$sth_insert->execute(undef, $new->id) $sth_insert->execute(undef, $new->id)
unless defined $workflow->{0}->{$new->id}; unless defined $workflow->{0}->{$new->id};
} }

View File

@ -645,12 +645,12 @@ my $initial_statuses = Bugzilla::Status->can_change_to();
# Exclude closed states from the UI, even if the workflow allows them. # Exclude closed states from the UI, even if the workflow allows them.
# The back-end code will still accept them, though. # The back-end code will still accept them, though.
@$initial_statuses = grep { $_->name eq 'RESOLVED' || $_->is_open } @$initial_statuses; @$initial_statuses = grep { $_->name eq Bugzilla->params->{duplicate_or_move_bug_status} || $_->is_open } @$initial_statuses;
if (!$product->allows_unconfirmed) if (!$product->allows_unconfirmed)
{ {
# UNCONFIRMED is illegal if allows_unconfirmed is false. # UNCONFIRMED is illegal if allows_unconfirmed is false.
@$initial_statuses = grep { $_->name ne 'UNCONFIRMED' } @$initial_statuses; @$initial_statuses = grep { $_->is_confirmed } @$initial_statuses;
} }
scalar(@$initial_statuses) || ThrowUserError('no_initial_bug_status'); scalar(@$initial_statuses) || ThrowUserError('no_initial_bug_status');
@ -658,7 +658,8 @@ scalar(@$initial_statuses) || ThrowUserError('no_initial_bug_status');
unless ($has_editbugs || $has_canconfirm) unless ($has_editbugs || $has_canconfirm)
{ {
# ... use UNCONFIRMED if available, else use the first status of the list. # ... use UNCONFIRMED if available, else use the first status of the list.
my $bug_status = (grep { $_->name eq 'UNCONFIRMED' } @$initial_statuses) ? 'UNCONFIRMED' : $initial_statuses->[0]; my ($bug_status) = grep { !$_->is_confirmed } @$initial_statuses;
$bug_status ||= $initial_statuses->[0];
@$initial_statuses = ($bug_status); @$initial_statuses = ($bug_status);
} }

View File

@ -919,7 +919,7 @@ sub process_bug {
# entry in the dup table. Since we can't tell the bug ID of bugs # entry in the dup table. Since we can't tell the bug ID of bugs
# that might not yet be in the database we have no way of populating # that might not yet be in the database we have no way of populating
# this table. Change the resolution instead. # this table. Change the resolution instead.
if ( $valid_res && ( $bug_fields{'resolution'} eq "DUPLICATE" ) ) { if ( $valid_res && ( $bug_fields{'resolution'} eq 'DUPLICATE' ) ) {
$resolution = "MOVED"; $resolution = "MOVED";
$err .= "This bug was marked DUPLICATE in the database "; $err .= "This bug was marked DUPLICATE in the database ";
$err .= "it was moved from.\n Changing resolution to \"MOVED\"\n"; $err .= "it was moved from.\n Changing resolution to \"MOVED\"\n";
@ -928,7 +928,7 @@ sub process_bug {
# If there is at least 1 initial bug status different from UNCO, use it, # If there is at least 1 initial bug status different from UNCO, use it,
# else use the open bug status with the lowest sortkey (different from UNCO). # else use the open bug status with the lowest sortkey (different from UNCO).
my @bug_statuses = @{Bugzilla::Status->can_change_to()}; my @bug_statuses = @{Bugzilla::Status->can_change_to()};
@bug_statuses = grep { $_->name ne 'UNCONFIRMED' } @bug_statuses; @bug_statuses = grep { $_->is_confirmed } @bug_statuses;
my $initial_status; my $initial_status;
if (scalar(@bug_statuses)) { if (scalar(@bug_statuses)) {
@ -937,7 +937,7 @@ sub process_bug {
else { else {
@bug_statuses = Bugzilla::Status->get_all(); @bug_statuses = Bugzilla::Status->get_all();
# Exclude UNCO and inactive bug statuses. # Exclude UNCO and inactive bug statuses.
@bug_statuses = grep { $_->is_active && $_->name ne 'UNCONFIRMED'} @bug_statuses; @bug_statuses = grep { $_->is_active && $_->is_confirmed } @bug_statuses;
my @open_statuses = grep { $_->is_open } @bug_statuses; my @open_statuses = grep { $_->is_open } @bug_statuses;
if (scalar(@open_statuses)) { if (scalar(@open_statuses)) {
$initial_status = $open_statuses[0]->name; $initial_status = $open_statuses[0]->name;
@ -961,6 +961,7 @@ sub process_bug {
$status = $initial_status; $status = $initial_status;
} }
else{ else{
# FIXME Remove bug_status==UNCONFIRMED hardcode
$status = "UNCONFIRMED"; $status = "UNCONFIRMED";
} }
if ($status ne $bug_fields{'bug_status'}){ if ($status ne $bug_fields{'bug_status'}){
@ -970,6 +971,7 @@ sub process_bug {
} }
} }
if($everconfirmed){ if($everconfirmed){
# FIXME Remove bug_status==UNCONFIRMED hardcode
if($status eq "UNCONFIRMED"){ if($status eq "UNCONFIRMED"){
$err .= "Bug Status was UNCONFIRMED but everconfirmed was true\n"; $err .= "Bug Status was UNCONFIRMED but everconfirmed was true\n";
$err .= " Setting status to $initial_status\n"; $err .= " Setting status to $initial_status\n";
@ -978,6 +980,7 @@ sub process_bug {
} }
} }
else{ # $everconfirmed is false else{ # $everconfirmed is false
# FIXME Remove bug_status==UNCONFIRMED hardcode
if($status ne "UNCONFIRMED"){ if($status ne "UNCONFIRMED"){
$err .= "Bug Status was $status but everconfirmed was false\n"; $err .= "Bug Status was $status but everconfirmed was false\n";
$err .= " Setting status to UNCONFIRMED\n"; $err .= " Setting status to UNCONFIRMED\n";

View File

@ -226,6 +226,7 @@ if ($cgi->param('repair_creation_date')) {
if ($cgi->param('repair_everconfirmed')) { if ($cgi->param('repair_everconfirmed')) {
Status('everconfirmed_start'); Status('everconfirmed_start');
# FIXME Remove bug_status==UNCONFIRMED hardcode
my @confirmed_open_states = grep {$_ ne 'UNCONFIRMED'} BUG_STATE_OPEN; my @confirmed_open_states = grep {$_ ne 'UNCONFIRMED'} BUG_STATE_OPEN;
my $confirmed_open_states = join(', ', map {$dbh->quote($_)} @confirmed_open_states); my $confirmed_open_states = join(', ', map {$dbh->quote($_)} @confirmed_open_states);

View File

@ -1,25 +1,7 @@
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*- # (Rewritten) Bug dependency graph display
# # License: Dual-license GPL 3.0+ or MPL 1.1+
# The contents of this file are subject to the Mozilla Public # Author(s): Vitaliy Filippov <vitalif@mail.ru>
# 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 Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Gervase Markham <gerv@gerv.net>
use utf8; use utf8;
use strict; use strict;
@ -44,7 +26,8 @@ my $vars = {};
# Check params # Check params
my $display = $cgi->param('display') || 'tree'; my $display = $cgi->param('display') || 'tree';
if (!defined $cgi->param('id') && $display ne 'doall') { if (!defined $cgi->param('id') && $display ne 'doall')
{
ThrowCodeError("missing_bug_id"); ThrowCodeError("missing_bug_id");
} }
@ -376,24 +359,28 @@ sub GetNodes
my $nodes = {}; my $nodes = {};
my $bugtitles = {}; my $bugtitles = {};
# Retrieve bug information from the database # Retrieve bug information from the database
# FIXME: Use Bugzilla::Search for this query
my $rows = Bugzilla->dbh->selectall_arrayref( my $rows = Bugzilla->dbh->selectall_arrayref(
"SELECT "SELECT
t1.bug_id, t1.bug_id,
t1.bug_status, bs.value bug_status,
t1.resolution, res.value resolution,
t1.short_desc, t1.short_desc,
t1.estimated_time, t1.estimated_time,
SUM(t3.work_time) AS work_time, SUM(t3.work_time) AS work_time,
t1.assigned_to, t1.assigned_to,
t2.login_name AS assigned_to_login, t2.login_name AS assigned_to_login,
t4.name AS product, p.name AS product,
t5.name AS component, c.name AS component,
t1.bug_severity sev.value bug_severity
FROM bugs AS t1 FROM bugs AS t1
LEFT JOIN bug_status AS bs ON bs.id=t1.bug_status
LEFT JOIN resolution AS res ON res.id=t1.resolution
LEFT JOIN bug_severity AS sev ON sev.id=t1.bug_severity
LEFT JOIN profiles AS t2 ON t2.userid=t1.assigned_to LEFT JOIN profiles AS t2 ON t2.userid=t1.assigned_to
LEFT JOIN longdescs AS t3 ON t3.bug_id=t1.bug_id AND t3.work_time > 0 LEFT JOIN longdescs AS t3 ON t3.bug_id=t1.bug_id AND t3.work_time > 0
LEFT JOIN products AS t4 ON t4.id=t1.product_id LEFT JOIN products AS p ON p.id=t1.product_id
LEFT JOIN components AS t5 ON t5.id=t1.component_id LEFT JOIN components AS c ON c.id=t1.component_id
WHERE t1.bug_id IN (".join(",", ("?") x scalar keys %$seen).") WHERE t1.bug_id IN (".join(",", ("?") x scalar keys %$seen).")
GROUP BY t1.bug_id", {Slice=>{}}, keys %$seen) || {}; GROUP BY t1.bug_id", {Slice=>{}}, keys %$seen) || {};
foreach my $row (@$rows) foreach my $row (@$rows)
@ -523,7 +510,8 @@ sub CleanupOldDots
# symlinks), this can't escape to delete anything it shouldn't # symlinks), this can't escape to delete anything it shouldn't
# (unless someone moves the location of $webdotdir, of course) # (unless someone moves the location of $webdotdir, of course)
trick_taint($f); trick_taint($f);
if (file_mod_time($f) < $since) { if (file_mod_time($f) < $since)
{
unlink $f; unlink $f;
} }
} }
@ -533,6 +521,7 @@ sub GetColorByState
{ {
my ($state, $base) = (@_); my ($state, $base) = (@_);
$base = $base ? 0 : 0x40; $base = $base ? 0 : 0x40;
# FIXME Remove bug_status hardcode
my %colorbystate = ( my %colorbystate = (
UNCONFIRMED => 'ffffff', UNCONFIRMED => 'ffffff',
NEW => 'ff8000', NEW => 'ff8000',

View File

@ -94,6 +94,7 @@ td.bz_total {
.bz_buglist .bz_dependson_column { width: 8%; white-space: normal; } .bz_buglist .bz_dependson_column { width: 8%; white-space: normal; }
/* Bug states - duplicated here for external stylesheet usage */ /* Bug states - duplicated here for external stylesheet usage */
/* FIXME: remove bug_status hardcode */
.bz_st_UNCONFIRMED, .bz_UNCONFIRMED td.first-child a { font-style: italic; } .bz_st_UNCONFIRMED, .bz_UNCONFIRMED td.first-child a { font-style: italic; }
.bz_st_RESOLVED, .bz_RESOLVED td.first-child a { text-decoration: line-through; } .bz_st_RESOLVED, .bz_RESOLVED td.first-child a { text-decoration: line-through; }
.bz_st_VERIFIED, .bz_VERIFIED td.first-child a { text-decoration: line-through; border: 1px dashed #2f6fab; margin: 0 -1px; color: black; background-color: #f9f9f9; line-height: 1.1em; } .bz_st_VERIFIED, .bz_VERIFIED td.first-child a { text-decoration: line-through; border: 1px dashed #2f6fab; margin: 0 -1px; color: black; background-color: #f9f9f9; line-height: 1.1em; }

View File

@ -504,6 +504,7 @@ form#Create .comment {
} }
/* Bug states */ /* Bug states */
/* FIXME remove bug_status hardcode */
.bz_st_UNCONFIRMED, .bz_UNCONFIRMED td.first-child a { font-style: italic; } .bz_st_UNCONFIRMED, .bz_UNCONFIRMED td.first-child a { font-style: italic; }
.bz_st_RESOLVED, .bz_RESOLVED td.first-child a { text-decoration: line-through; } .bz_st_RESOLVED, .bz_RESOLVED td.first-child a { text-decoration: line-through; }
.bz_st_VERIFIED, .bz_VERIFIED td.first-child a { text-decoration: line-through; border: 1px dashed #2f6fab; margin: 0 -1px; color: black; background-color: #f9f9f9; line-height: 1.1em; } .bz_st_VERIFIED, .bz_VERIFIED td.first-child a { text-decoration: line-through; border: 1px dashed #2f6fab; margin: 0 -1px; color: black; background-color: #f9f9f9; line-height: 1.1em; }

View File

@ -142,7 +142,7 @@ document.write('<input type="button" value="Disable All Mail" onclick="SetCheckb
[% neg_events = [ [% neg_events = [
{ id = constants.EVT_UNCONFIRMED, { id = constants.EVT_UNCONFIRMED,
description = "The $terms.bug is in the UNCONFIRMED state" }, description = "The $terms.bug is in the unconfirmed state" },
{ id = constants.EVT_CHANGED_BY_ME, { id = constants.EVT_CHANGED_BY_ME,
description = "The change was made by me" }, description = "The change was made by me" },
] %] ] %]

View File

@ -30,7 +30,7 @@
<table border="0" cellpadding="4" cellspacing="0"> <table border="0" cellpadding="4" cellspacing="0">
<tr> <tr>
<th valign="top" align="right"> <th valign="top" align="left">
<label for="value_new">Field Value:</label> <label for="value_new">Field Value:</label>
</th> </th>
<td> <td>
@ -46,19 +46,33 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<th align="right"><label for="sortkey">Sortkey:</label></th> <th align="left"><label for="sortkey">Sortkey:</label></th>
<td><input id="sortkey" size="6" maxlength="6" name="sortkey" <td><input id="sortkey" size="6" maxlength="6" name="sortkey"
value="[%- value.sortkey FILTER html %]" /></td> value="[%- value.sortkey FILTER html %]" /></td>
</tr> </tr>
[% IF field.name == "bug_status" %] [% IF field.name == "bug_status" %]
<tr> <tr>
<th align="right"><label for="is_open">Status Type:</label></th> <th align="left"><label for="is_open">Status Type:</label></th>
<td>[% IF value.is_open %]Open[% ELSE %]Closed[% END %]</td> <td>[% IF value.is_open %]Open[% ELSE %]Closed[% END %]</td>
</tr> </tr>
<tr>
<th align="left"><label for="is_assigned">Is it an assigned state?</label></th>
<td>
<input id="is_assigned" name="is_assigned" type="checkbox" value="1"
[%+ 'checked="checked"' IF value.is_assigned %] />
</td>
</tr>
<tr>
<th align="left"><label for="is_confirmed">Is it a confirmed state?</label></th>
<td>
<input id="is_confirmed" name="is_confirmed" type="checkbox" value="1"
[%+ 'checked="checked"' IF value.is_confirmed %] />
</td>
</tr>
[% END %] [% END %]
[% IF field.value_field && !value.is_static %] [% IF field.value_field && !value.is_static %]
<tr> <tr>
<th align="right"> <th align="left">
Only appears when [%+ field.value_field.description FILTER html %] is set to: Only appears when [%+ field.value_field.description FILTER html %] is set to:
</th> </th>
<td> <td>
@ -79,10 +93,10 @@
</tr> </tr>
[% END %] [% END %]
<tr> <tr>
<th align="right"><label for="is_active">Enabled for [% terms.bugs %]:</label></th> <th align="left"><label for="isactive">Enabled for [% terms.bugs %]:</label></th>
<td> <td>
<input id="is_active" name="is_active" type="checkbox" value="1" <input id="isactive" name="isactive" type="checkbox" value="1"
[%+ 'checked="checked"' IF value.is_active %] [%+ 'checked="checked"' IF value.isactive %]
[%+ 'disabled="disabled"' IF value.is_default OR value.is_static %] /> [%+ 'disabled="disabled"' IF value.is_default OR value.is_static %] />
[% IF value.is_default %] [% IF value.is_default %]
This value is selected as default in the parameters for this field. It cannot be disabled. This value is selected as default in the parameters for this field. It cannot be disabled.

View File

@ -49,9 +49,8 @@
</tr> </tr>
<tr> <tr>
<th align="right"> <th align="right">
<label for="allows_unconfirmed">Enable the <label for="allows_unconfirmed">Enable unconfirmed
UNCONFIRMED status bug state(s) in this product:</label>
in this product:</label>
</th> </th>
<td><input type="checkbox" id="allows_unconfirmed" name="allows_unconfirmed" <td><input type="checkbox" id="allows_unconfirmed" name="allows_unconfirmed"
[% ' checked="checked"' IF product.allows_unconfirmed %] [% ' checked="checked"' IF product.allows_unconfirmed %]

View File

@ -104,16 +104,13 @@
[% IF changes.allows_unconfirmed.defined %] [% IF changes.allows_unconfirmed.defined %]
<p> <p>
[% IF product.allows_unconfirmed %] [% IF product.allows_unconfirmed %]
The product now allows the The product now allows unconfirmed states.
UNCONFIRMED status.
[% ELSE %] [% ELSE %]
The product no longer allows the The product no longer allows unconfirmed states.
UNCONFIRMED status.
Note that any Note that any
<a href="buglist.cgi?product= <a href="buglist.cgi?product=[%- product.name FILTER url_quote %][% FOR s = unconfirmed_states %]&amp;bug_status=[% s | url_quote %][% END %]">
[%- product.name FILTER url_quote %]&amp;bug_status=UNCONFIRMED"> [%- terms.bugs %] that currently have unconfirmed states
[%- terms.bugs %] that currently have the </a>
UNCONFIRMED status</a>
will remain in that status until they are edited. will remain in that status until they are edited.
[% END %] [% END %]
</p> </p>

View File

@ -30,6 +30,7 @@
//--> //-->
</script> </script>
[%# FIXME Check if this is correct about 'one of either UNCONFIRMED or REOPENED' %]
<p> <p>
This page allows you to define which status transitions are valid in your workflow. This page allows you to define which status transitions are valid in your workflow.
For compatibility with older versions of [% terms.Bugzilla %], reopening [% terms.abug %] For compatibility with older versions of [% terms.Bugzilla %], reopening [% terms.abug %]
@ -66,7 +67,7 @@
</th> </th>
[% FOREACH new_status = statuses %] [% FOREACH new_status = statuses %]
[% IF status.id != new_status.id && (status.id || new_status.name == 'RESOLVED' || new_status.is_open) %] [% IF status.id != new_status.id && (status.id || new_status.name == Param('duplicate_or_move_bug_status') || new_status.is_open) %]
[% checked = workflow.${status.id}.${new_status.id}.defined ? 1 : 0 %] [% checked = workflow.${status.id}.${new_status.id}.defined ? 1 : 0 %]
[% mandatory = (status.id && new_status.name == Param("duplicate_or_move_bug_status")) ? 1 : 0 %] [% mandatory = (status.id && new_status.name == Param("duplicate_or_move_bug_status")) ? 1 : 0 %]
<td align="center" class="checkbox-cell[% " checked" IF checked || mandatory %]" <td align="center" class="checkbox-cell[% " checked" IF checked || mandatory %]"

View File

@ -78,11 +78,7 @@
</tr> </tr>
[% END %] [% END %]
[% bug_statuses = [] %] [% bug_statuses = bug.statuses_available %]
[% FOREACH bug_status = bug.status.can_change_to %]
[% NEXT IF bug_status.name == "UNCONFIRMED" && !bug.product_obj.allows_unconfirmed %]
[% bug_statuses.push(bug_status) %]
[% END %]
[% IF bug_statuses.size %] [% IF bug_statuses.size %]
<tr> <tr>
<th><label for="bug_status">Change bug status to:</label></th> <th><label for="bug_status">Change bug status to:</label></th>
@ -95,7 +91,7 @@
[% END %] [% END %]
</select> </select>
[% IF bug.resolution OR bug.check_can_change_field('resolution', bug.resolution, 1) %] [% IF bug.resolution OR bug.check_can_change_field('resolution', bug.resolution, 1) %]
<noscript><br>resolved&nbsp;as&nbsp;</noscript> <noscript><br />resolved&nbsp;as&nbsp;</noscript>
[% END %] [% END %]
<span id="resolution_settings"> <span id="resolution_settings">
@ -107,12 +103,14 @@
%] %]
</span> </span>
<script type="text/javascript"> <script type="text/javascript">
[%# FIXME Move close_status_array into "js resource data" %]
var close_status_array = [ var close_status_array = [
[% FOREACH status = bug.statuses_available %] [% SET i = 0 %]
[% NEXT IF status.is_open %] [% FOREACH status = bug.statuses_available %]
'[% status.name FILTER js %]'[% ',' UNLESS loop.last %] [% NEXT IF status.is_open %]
[% END %] [% ',' IF i; SET i = 1 %]'[% status.name FILTER js %]'
]; [% END %]
];
function onchange_bug_status() function onchange_bug_status()
{ {
showHideStatusItems('[% "is_duplicate" IF bug.dup_id %]', '[% bug.bug_status | js %]'); showHideStatusItems('[% "is_duplicate" IF bug.dup_id %]', '[% bug.bug_status | js %]');

View File

@ -44,6 +44,7 @@
[% PROCESS global/header.html.tmpl %] [% PROCESS global/header.html.tmpl %]
[%# FIXME: Remove bug_status hardcode %]
<table cellpadding="2" style="margin-bottom: 16px; border: 1px solid gray; background-color: white"> <table cellpadding="2" style="margin-bottom: 16px; border: 1px solid gray; background-color: white">
<tr> <tr>
<td>Bug states:</td> <td>Bug states:</td>

View File

@ -69,10 +69,12 @@
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
[%# FIXME Move close_status_array into "js resource data" %]
var close_status_array = [ var close_status_array = [
[% SET i = 0 %]
[% FOREACH status = bug.statuses_available %] [% FOREACH status = bug.statuses_available %]
[% NEXT IF status.is_open %] [% NEXT IF status.is_open %]
'[% status.name FILTER js %]'[% ',' UNLESS loop.last %] [% ',' IF i; SET i = 1 %]'[% status.name FILTER js %]'
[% END %] [% END %]
]; ];
removeClass('dup_id_discoverable', 'bz_default_hidden'); removeClass('dup_id_discoverable', 'bz_default_hidden');
@ -84,6 +86,7 @@ function onchange_bug_status()
{ {
showHideStatusItems('[% "is_duplicate" IF bug.dup_id %]', '[% bug.bug_status_obj.name | js %]'); showHideStatusItems('[% "is_duplicate" IF bug.dup_id %]', '[% bug.bug_status_obj.name | js %]');
var s = document.getElementById('bug_status'); var s = document.getElementById('bug_status');
[%# FIXME Remove hardcode bug_status==ASSIGNED => assign to self, bug_status==VERIFIED => qa to self %]
if (s.value == "ASSIGNED" && document.changeform.assigned_to.value != "[% user.login %]") if (s.value == "ASSIGNED" && document.changeform.assigned_to.value != "[% user.login %]")
{ {
document.changeform.assigned_to.value = "[% user.login %]"; document.changeform.assigned_to.value = "[% user.login %]";

View File

@ -448,8 +448,7 @@
[% BLOCK error_no_open_bug_status %] [% BLOCK error_no_open_bug_status %]
[% title = "$terms.Bug Cannot Be Confirmed" %] [% title = "$terms.Bug Cannot Be Confirmed" %]
There is no valid transition from There is no valid transition to an open confirmed state.
UNCONFIRMED to an open state.
[% END %] [% END %]
[% BLOCK error_param_invalid %] [% BLOCK error_param_invalid %]

View File

@ -355,6 +355,13 @@
[% IF changes.isactive %] [% IF changes.isactive %]
<li>It is now [% IF changes.isactive.1 %]enabled[% ELSE %]disabled[% END %] for selection.</li> <li>It is now [% IF changes.isactive.1 %]enabled[% ELSE %]disabled[% END %] for selection.</li>
[% END %] [% END %]
[%# For bug_status: %]
[% IF changes.is_assigned %]
<li>It is now an [% IF changes.is_assigned.1 %]"Assigned" (in-progress)[% ELSE %]normal[% END %] state.</li>
[% END %]
[% IF changes.is_confirmed %]
<li>It is now [% IF changes.is_confirmed.1 %]a confirmed[% ELSE %]an unconfirmed[% END %] state.</li>
[% END %]
[% IF changes.visibility_values.defined %] [% IF changes.visibility_values.defined %]
[% IF value.visibility_values.size > 0 %] [% IF value.visibility_values.size > 0 %]
<li>It only appears when <li>It only appears when

View File

@ -404,13 +404,14 @@ document.write(' <input type="button" name="check_all" value="Check All" onclick
<option value="[% dontchange FILTER html %]" selected >[% dontchange FILTER html %]</option> <option value="[% dontchange FILTER html %]" selected >[% dontchange FILTER html %]</option>
[% FOREACH r = resolutions %] [% FOREACH r = resolutions %]
[% NEXT IF !r %] [% NEXT IF !r %]
[% NEXT IF r == "DUPLICATE" || r == "MOVED" %] [% NEXT IF r == Param('duplicate_resolution') || r == "MOVED" %]
<option value="[% r FILTER html %]">[% r FILTER html %]</option> <option value="[% r FILTER html %]">[% r FILTER html %]</option>
[% END %] [% END %]
</select> </select>
</span> </span>
<script type="text/javascript"> <script type="text/javascript">
[%# FIXME Move close_status_array into js resource data %]
var close_status_array = new Array("[% closed_status_array.join('", "') FILTER none %]"); var close_status_array = new Array("[% closed_status_array.join('", "') FILTER none %]");
addListener('bug_status', "change", function() { showHideStatusItems('', '') }); addListener('bug_status', "change", function() { showHideStatusItems('', '') });
addListener(window, 'load', function() { showHideStatusItems('', '') }); addListener(window, 'load', function() { showHideStatusItems('', '') });

View File

@ -80,11 +80,13 @@ END:VCALENDAR
[% END %] [% END %]
[% END %] [% END %]
[% IF NOT status %] [% IF NOT status %]
[% IF bug_status == 'ASSIGNED' %] [% FOREACH state = assignedstates %]
[% status = 'IN-PROGRESS' %] [% IF bug_status == state %]
[% ELSE %] [% status = 'IN-PROGRESS' %]
[% status = 'NEEDS-ACTION' %] [% END %]
[% END %] [% END %]
[% IF NOT status %]
[% status = 'NEEDS-ACTION' %]
[% END %] [% END %]
[% status FILTER ics('STATUS') %] [% status FILTER ics('STATUS') %]
[% END %] [% END %]

View File

@ -1,6 +1,4 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public # The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file # License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of # except in compliance with the License. You may obtain a copy of
@ -23,9 +21,9 @@
# Frédéric Buclin <LpSolit@gmail.com> # Frédéric Buclin <LpSolit@gmail.com>
# This is a script suitable for running once a day from a cron job. It # This is a script suitable for running once a day from a cron job. It
# looks at all the bugs, and sends whiny mail to anyone who has a bug # looks at all the bugs, and sends whiny mail to anyone who has a bug
# assigned to them that has status NEW or REOPENED that has not been # assigned to them that has unassigned, but open status that has not been
# touched for more than the number of days specified in the whinedays param. # touched for more than the number of days specified in the whinedays param.
use strict; use strict;
@ -37,61 +35,63 @@ use Bugzilla::Util;
use Bugzilla::User; use Bugzilla::User;
# Whining is disabled if whinedays is zero # Whining is disabled if whinedays is zero
exit unless Bugzilla->params->{'whinedays'} >= 1; exit unless Bugzilla->params->{whinedays} >= 1;
my $dbh = Bugzilla->dbh; my $dbh = Bugzilla->dbh;
my $query = q{SELECT bug_id, short_desc, login_name my $query = "SELECT b.bug_id, b.short_desc, p.login_name FROM bugs b".
FROM bugs " INNER JOIN bug_status bs ON bs.id=b.bug_status".
INNER JOIN profiles " INNER JOIN profiles p ON p.userid = b.assigned_to".
ON userid = assigned_to " WHERE bs.is_open AND NOT bs.is_assigned".
WHERE (bug_status = ? OR bug_status = ?) " AND disable_mail = 0 AND " . $dbh->sql_to_days('NOW()') . " - " .
AND disable_mail = 0 $dbh->sql_to_days('delta_ts') . " > " . Bugzilla->params->{whinedays} .
AND } . $dbh->sql_to_days('NOW()') . " - " . " ORDER BY bug_id";
$dbh->sql_to_days('delta_ts') . " > " .
Bugzilla->params->{'whinedays'} .
" ORDER BY bug_id";
my %bugs; my %bugs;
my %desc; my %desc;
# FIXME: Remove status hardcode: NEW | REOPENED == is_open & !ASSIGNED my $slt_bugs = $dbh->selectall_arrayref($query);
my $slt_bugs = $dbh->selectall_arrayref($query, undef, 'NEW', 'REOPENED');
foreach my $bug (@$slt_bugs) { foreach my $bug (@$slt_bugs)
{
my ($id, $desc, $email) = @$bug; my ($id, $desc, $email) = @$bug;
if (!defined $bugs{$email}) { if (!defined $bugs{$email})
{
$bugs{$email} = []; $bugs{$email} = [];
} }
if (!defined $desc{$email}) { if (!defined $desc{$email})
{
$desc{$email} = []; $desc{$email} = [];
} }
push @{$bugs{$email}}, $id; push @{$bugs{$email}}, $id;
push @{$desc{$email}}, $desc; push @{$desc{$email}}, $desc;
} }
foreach my $email (sort keys %bugs)
foreach my $email (sort (keys %bugs)) { {
my $user = new Bugzilla::User({name => $email}); my $user = new Bugzilla::User({ name => $email });
next if $user->email_disabled; next if $user->email_disabled;
my $vars = {'email' => $email}; my $vars = {email => $email};
my @bugs = (); my @bugs = ();
foreach my $i (@{$bugs{$email}}) { foreach my $i (@{$bugs{$email}})
{
my $bug = {}; my $bug = {};
$bug->{'summary'} = shift(@{$desc{$email}}); $bug->{summary} = shift(@{$desc{$email}});
$bug->{'id'} = $i; $bug->{id} = $i;
push @bugs, $bug; push @bugs, $bug;
} }
$vars->{'bugs'} = \@bugs; $vars->{bugs} = \@bugs;
my $msg; my $msg;
my $template = Bugzilla->template_inner($user->settings->{'lang'}->{'value'}); my $template = Bugzilla->template_inner($user->settings->{lang}->{value});
$template->process("email/whine.txt.tmpl", $vars, \$msg) $template->process("email/whine.txt.tmpl", $vars, \$msg)
or die($template->error()); || die($template->error);
Bugzilla->template_inner(""); Bugzilla->template_inner("");
MessageToMTA($msg); MessageToMTA($msg);
print "$email " . join(" ", @{$bugs{$email}}) . "\n"; print "$email " . join(" ", @{$bugs{$email}}) . "\n";
} }
exit;