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.
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;
}

View File

@ -1431,7 +1431,7 @@ Bugzilla::DB - Database access routines, using L<DBI>
# prepare a query using DB methods
my $sth = $dbh->prepare("SELECT " .
$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));
# Execute the query

View File

@ -157,17 +157,6 @@ sub update
if (exists $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)
{
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' });
}
# 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 #
################################################################

View File

@ -128,30 +128,8 @@ sub update
my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction();
# Not Bugzilla::Field::Choice! It will overwrite other products' bug values
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
$self->set_visibility_values([ $self->product_id ]);
@ -162,36 +140,41 @@ sub update
return $changes;
}
sub remove_from_db {
sub remove_from_db
{
my $self = shift;
my $dbh = Bugzilla->dbh;
# 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 });
}
if ($self->bug_count) {
if ($self->bug_count)
{
# We don't want to delete bugs when deleting a milestone.
# Bugs concerned are reassigned to the default milestone.
my $bug_ids =
$dbh->selectcol_arrayref('SELECT bug_id FROM bugs
WHERE product_id = ? AND target_milestone = ?',
undef, ($self->product->id, $self->name));
my $bug_ids = $dbh->selectcol_arrayref(
'SELECT bug_id FROM bugs WHERE product_id = ? AND target_milestone = ?',
undef, ($self->product->id, $self->id)
);
my $timestamp = $dbh->selectrow_array('SELECT NOW()');
$dbh->do('UPDATE bugs SET target_milestone = ?, delta_ts = ?
WHERE ' . $dbh->sql_in('bug_id', $bug_ids),
undef, ($self->product->default_milestone, $timestamp));
$dbh->do(
'UPDATE bugs SET target_milestone = ?, delta_ts = ? WHERE ' . $dbh->sql_in('bug_id', $bug_ids),
undef, ($self->product->default_milestone, $timestamp)
);
require Bugzilla::Bug;
import Bugzilla::Bug qw(LogActivityEntry);
foreach my $bug_id (@$bug_ids) {
LogActivityEntry($bug_id, 'target_milestone',
$self->name,
$self->product->default_milestone,
Bugzilla->user->id, $timestamp);
my $def = Bugzilla::Milestone->new($self->product->default_milestone);
foreach my $bug_id (@$bug_ids)
{
Bugzilla::Bug::LogActivityEntry(
$bug_id, 'target_milestone', $self->name,
$def && $def->name, Bugzilla->user->id, $timestamp
);
}
}
@ -249,17 +232,19 @@ sub _check_product {
sub set_name { $_[0]->set('value', $_[1]); }
sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
sub bug_count {
sub bug_count
{
my $self = shift;
my $dbh = Bugzilla->dbh;
if (!defined $self->{'bug_count'}) {
$self->{'bug_count'} = $dbh->selectrow_array(q{
SELECT COUNT(*) FROM bugs
WHERE product_id = ? AND target_milestone = ?},
undef, $self->product_id, $self->name) || 0;
if (!defined $self->{bug_count})
{
$self->{bug_count} = $dbh->selectrow_array(
"SELECT COUNT(*) FROM bugs WHERE product_id = ? AND target_milestone = ?",
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
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
@ -17,6 +15,8 @@
# Andreas Franke <afranke@mathweb.org>
# Stephen Lee <slee@uk.bnsmc.com>
# Marc Schumann <wurblzap@gmail.com>
#
# Refactoring by Vitaliy Filippov <vitalif@mail.ru>
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 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
{
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
@ -56,6 +61,8 @@ sub VALIDATORS
my $invocant = shift;
my $validators = $invocant->SUPER::VALIDATORS;
$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;
return $validators;
}
@ -91,15 +98,13 @@ sub remove_from_db
sub is_active { return $_[0]->{isactive}; }
sub is_open { return $_[0]->{is_open}; }
sub is_assigned { return $_[0]->{is_assigned}; }
sub is_confirmed { return $_[0]->{is_confirmed}; }
sub is_static
{
my $self = shift;
if ($self->name eq 'UNCONFIRMED' || $self->name eq Bugzilla->params->{duplicate_or_move_bug_status})
{
return 1;
}
return 0;
return $self->name eq Bugzilla->params->{duplicate_or_move_bug_status} ? 1 : 0;
}
##############

View File

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

View File

@ -1549,17 +1549,19 @@ sub wants_bug_mail {
$wants_mail &= $self->wants_mail([EVT_CHANGED_BY_ME], $relationship);
}
if ($wants_mail) {
if ($wants_mail)
{
my $dbh = Bugzilla->dbh;
# 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
# down bugmail sending by a factor of 2. If Bug creation was more
# lazy, this might not be so bad.
my $bug_status = $dbh->selectrow_array('SELECT bug_status
FROM bugs WHERE bug_id = ?',
undef, $bug_id);
if ($bug_status eq "UNCONFIRMED") {
# FIXME: db abstraction?... or cache this value?...
my ($is_confirmed) = $dbh->selectrow_array(
'SELECT bs.is_confirmed FROM bugs b, bug_status bs WHERE b.bug_id=? AND bs.id=b.bug_status', undef, $bug_id
);
if (!$is_confirmed)
{
$wants_mail &= $self->wants_mail([EVT_UNCONFIRMED], $relationship);
}
}

View File

@ -115,17 +115,18 @@ sub run_create_validators {
return $params;
}
sub bug_count {
sub bug_count
{
my $self = shift;
my $dbh = Bugzilla->dbh;
if (!defined $self->{'bug_count'}) {
$self->{'bug_count'} = $dbh->selectrow_array(qq{
SELECT COUNT(*) FROM bugs
WHERE product_id = ? AND version = ?}, undef,
($self->product_id, $self->name)) || 0;
if (!defined $self->{bug_count})
{
$self->{bug_count} = $dbh->selectrow_array(
"SELECT COUNT(*) FROM bugs WHERE product_id = ? AND version = ?",
undef, ($self->product_id, $self->id)
) || 0;
}
return $self->{'bug_count'};
return $self->{bug_count};
}
sub create
@ -149,25 +150,8 @@ sub update
my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction();
# Not Bugzilla::Field::Choice! It will overwrite other products' bug values
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
$self->set_visibility_values([ $self->product_id ]);
@ -178,13 +162,13 @@ sub update
return $changes;
}
sub remove_from_db {
sub remove_from_db
{
my $self = shift;
my $dbh = Bugzilla->dbh;
# The version cannot be removed if there are bugs
# associated with it.
if ($self->bug_count) {
# The version cannot be removed if there are bugs associated with it.
if ($self->bug_count)
{
ThrowUserError("version_has_bugs", { nb => $self->bug_count });
}
# Remove visibility values

View File

@ -1184,7 +1184,9 @@ $vars->{columns} = $columns;
$vars->{displaycolumns} = \@displaycolumns;
$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)
# 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);
if ($regenerate) {
%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(
'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(
q{SELECT bugs_activity.bug_id, bugs_activity.removed,}
@ -209,8 +209,8 @@ sub collect_stats {
# Now collect current data.
my @row = (today());
my $status_sql = q{SELECT COUNT(*) FROM bugs WHERE bug_status = ?};
my $reso_sql = q{SELECT COUNT(*) FROM bugs WHERE resolution = ?};
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, resolution WHERE bugs.resolution=resolution.id AND resolution.value = ?};
if ($product ne '-All-') {
$status_sql .= q{ AND product_id = ?};

View File

@ -180,10 +180,11 @@ my %since_dups = @{$dbh->selectcol_arrayref(
"SELECT dupe_of, COUNT(dupe)
FROM duplicates INNER JOIN bugs_activity
ON bugs_activity.bug_id = duplicates.dupe
WHERE added = 'DUPLICATE' AND fieldid = ?
WHERE added = ? AND fieldid = ?
AND bug_when >= LOCALTIMESTAMP(0) - "
. $dbh->sql_interval('?', 'DAY') .
" GROUP BY dupe_of", {Columns=>[1,2]},
Bugzilla->params->{duplicate_resolution},
$reso_field_id, $changedsince)};
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->{'product'} = $product;
$vars->{unconfirmed_states} = [ map { $_->name } grep { !$_->is_confirmed } Bugzilla::Status->get_all ];
$vars->{'changes'} = $changes;
$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');
$vars->{value_old} = $value->name;
if ($value->can('set_timetracking'))
for ($value->UPDATE_COLUMNS)
{
$value->set_timetracking($ARGS->{timetracking} ? 1 : 0);
}
$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)
if ($_ ne 'isactive' && $_ ne $value->NAME_FIELD || !$value->is_static && !$value->is_default)
{
$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);
$vars->{changes} = $value->update;
$vars->{message} = 'field_value_updated';

View File

@ -85,7 +85,7 @@ elsif ($action eq 'update') {
# Part 1: Initial bug 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)
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.
# 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)
{
# 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');
@ -658,7 +658,8 @@ scalar(@$initial_statuses) || ThrowUserError('no_initial_bug_status');
unless ($has_editbugs || $has_canconfirm)
{
# ... 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);
}

View File

@ -919,7 +919,7 @@ sub process_bug {
# 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
# this table. Change the resolution instead.
if ( $valid_res && ( $bug_fields{'resolution'} eq "DUPLICATE" ) ) {
if ( $valid_res && ( $bug_fields{'resolution'} eq 'DUPLICATE' ) ) {
$resolution = "MOVED";
$err .= "This bug was marked DUPLICATE in the database ";
$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,
# else use the open bug status with the lowest sortkey (different from UNCO).
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;
if (scalar(@bug_statuses)) {
@ -937,7 +937,7 @@ sub process_bug {
else {
@bug_statuses = Bugzilla::Status->get_all();
# 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;
if (scalar(@open_statuses)) {
$initial_status = $open_statuses[0]->name;
@ -961,6 +961,7 @@ sub process_bug {
$status = $initial_status;
}
else{
# FIXME Remove bug_status==UNCONFIRMED hardcode
$status = "UNCONFIRMED";
}
if ($status ne $bug_fields{'bug_status'}){
@ -970,6 +971,7 @@ sub process_bug {
}
}
if($everconfirmed){
# FIXME Remove bug_status==UNCONFIRMED hardcode
if($status eq "UNCONFIRMED"){
$err .= "Bug Status was UNCONFIRMED but everconfirmed was true\n";
$err .= " Setting status to $initial_status\n";
@ -978,6 +980,7 @@ sub process_bug {
}
}
else{ # $everconfirmed is false
# FIXME Remove bug_status==UNCONFIRMED hardcode
if($status ne "UNCONFIRMED"){
$err .= "Bug Status was $status but everconfirmed was false\n";
$err .= " Setting status to UNCONFIRMED\n";

View File

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

View File

@ -1,25 +1,7 @@
#!/usr/bin/perl -wT
# -*- 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 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>
# (Rewritten) Bug dependency graph display
# License: Dual-license GPL 3.0+ or MPL 1.1+
# Author(s): Vitaliy Filippov <vitalif@mail.ru>
use utf8;
use strict;
@ -44,7 +26,8 @@ my $vars = {};
# Check params
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");
}
@ -376,24 +359,28 @@ sub GetNodes
my $nodes = {};
my $bugtitles = {};
# Retrieve bug information from the database
# FIXME: Use Bugzilla::Search for this query
my $rows = Bugzilla->dbh->selectall_arrayref(
"SELECT
t1.bug_id,
t1.bug_status,
t1.resolution,
bs.value bug_status,
res.value resolution,
t1.short_desc,
t1.estimated_time,
SUM(t3.work_time) AS work_time,
t1.assigned_to,
t2.login_name AS assigned_to_login,
t4.name AS product,
t5.name AS component,
t1.bug_severity
p.name AS product,
c.name AS component,
sev.value bug_severity
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 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 components AS t5 ON t5.id=t1.component_id
LEFT JOIN products AS p ON p.id=t1.product_id
LEFT JOIN components AS c ON c.id=t1.component_id
WHERE t1.bug_id IN (".join(",", ("?") x scalar keys %$seen).")
GROUP BY t1.bug_id", {Slice=>{}}, keys %$seen) || {};
foreach my $row (@$rows)
@ -523,7 +510,8 @@ sub CleanupOldDots
# symlinks), this can't escape to delete anything it shouldn't
# (unless someone moves the location of $webdotdir, of course)
trick_taint($f);
if (file_mod_time($f) < $since) {
if (file_mod_time($f) < $since)
{
unlink $f;
}
}
@ -533,6 +521,7 @@ sub GetColorByState
{
my ($state, $base) = (@_);
$base = $base ? 0 : 0x40;
# FIXME Remove bug_status hardcode
my %colorbystate = (
UNCONFIRMED => 'ffffff',
NEW => 'ff8000',

View File

@ -94,6 +94,7 @@ td.bz_total {
.bz_buglist .bz_dependson_column { width: 8%; white-space: normal; }
/* 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_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; }

View File

@ -504,6 +504,7 @@ form#Create .comment {
}
/* Bug states */
/* FIXME remove bug_status hardcode */
.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_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 = [
{ 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,
description = "The change was made by me" },
] %]

View File

@ -30,7 +30,7 @@
<table border="0" cellpadding="4" cellspacing="0">
<tr>
<th valign="top" align="right">
<th valign="top" align="left">
<label for="value_new">Field Value:</label>
</th>
<td>
@ -46,19 +46,33 @@
</td>
</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"
value="[%- value.sortkey FILTER html %]" /></td>
</tr>
[% IF field.name == "bug_status" %]
<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>
</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 %]
[% IF field.value_field && !value.is_static %]
<tr>
<th align="right">
<th align="left">
Only appears when [%+ field.value_field.description FILTER html %] is set to:
</th>
<td>
@ -79,10 +93,10 @@
</tr>
[% END %]
<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>
<input id="is_active" name="is_active" type="checkbox" value="1"
[%+ 'checked="checked"' IF value.is_active %]
<input id="isactive" name="isactive" type="checkbox" value="1"
[%+ 'checked="checked"' IF value.isactive %]
[%+ 'disabled="disabled"' IF value.is_default OR value.is_static %] />
[% IF value.is_default %]
This value is selected as default in the parameters for this field. It cannot be disabled.

View File

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

View File

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

View File

@ -30,6 +30,7 @@
//-->
</script>
[%# FIXME Check if this is correct about 'one of either UNCONFIRMED or REOPENED' %]
<p>
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 %]
@ -66,7 +67,7 @@
</th>
[% 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 %]
[% mandatory = (status.id && new_status.name == Param("duplicate_or_move_bug_status")) ? 1 : 0 %]
<td align="center" class="checkbox-cell[% " checked" IF checked || mandatory %]"

View File

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

View File

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

View File

@ -69,10 +69,12 @@
</div>
<script type="text/javascript">
[%# FIXME Move close_status_array into "js resource data" %]
var close_status_array = [
[% SET i = 0 %]
[% FOREACH status = bug.statuses_available %]
[% NEXT IF status.is_open %]
'[% status.name FILTER js %]'[% ',' UNLESS loop.last %]
[% ',' IF i; SET i = 1 %]'[% status.name FILTER js %]'
[% END %]
];
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 %]');
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 %]")
{
document.changeform.assigned_to.value = "[% user.login %]";

View File

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

View File

@ -355,6 +355,13 @@
[% IF changes.isactive %]
<li>It is now [% IF changes.isactive.1 %]enabled[% ELSE %]disabled[% END %] for selection.</li>
[% 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 value.visibility_values.size > 0 %]
<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>
[% FOREACH r = resolutions %]
[% 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>
[% END %]
</select>
</span>
<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 %]");
addListener('bug_status', "change", function() { showHideStatusItems('', '') });
addListener(window, 'load', function() { showHideStatusItems('', '') });

View File

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

View File

@ -1,6 +1,4 @@
#!/usr/bin/perl -w
# -*- 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
@ -23,9 +21,9 @@
# Frédéric Buclin <LpSolit@gmail.com>
# 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
# assigned to them that has status NEW or REOPENED that has not been
# 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
# 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.
use strict;
@ -37,61 +35,63 @@ use Bugzilla::Util;
use Bugzilla::User;
# Whining is disabled if whinedays is zero
exit unless Bugzilla->params->{'whinedays'} >= 1;
exit unless Bugzilla->params->{whinedays} >= 1;
my $dbh = Bugzilla->dbh;
my $query = q{SELECT bug_id, short_desc, login_name
FROM bugs
INNER JOIN profiles
ON userid = assigned_to
WHERE (bug_status = ? OR bug_status = ?)
AND disable_mail = 0
AND } . $dbh->sql_to_days('NOW()') . " - " .
$dbh->sql_to_days('delta_ts') . " > " .
Bugzilla->params->{'whinedays'} .
" ORDER BY bug_id";
my $query = "SELECT b.bug_id, b.short_desc, p.login_name FROM bugs b".
" INNER JOIN bug_status bs ON bs.id=b.bug_status".
" INNER JOIN profiles p ON p.userid = b.assigned_to".
" WHERE bs.is_open AND NOT bs.is_assigned".
" AND disable_mail = 0 AND " . $dbh->sql_to_days('NOW()') . " - " .
$dbh->sql_to_days('delta_ts') . " > " . Bugzilla->params->{whinedays} .
" ORDER BY bug_id";
my %bugs;
my %desc;
# FIXME: Remove status hardcode: NEW | REOPENED == is_open & !ASSIGNED
my $slt_bugs = $dbh->selectall_arrayref($query, undef, 'NEW', 'REOPENED');
my $slt_bugs = $dbh->selectall_arrayref($query);
foreach my $bug (@$slt_bugs) {
foreach my $bug (@$slt_bugs)
{
my ($id, $desc, $email) = @$bug;
if (!defined $bugs{$email}) {
if (!defined $bugs{$email})
{
$bugs{$email} = [];
}
if (!defined $desc{$email}) {
if (!defined $desc{$email})
{
$desc{$email} = [];
}
push @{$bugs{$email}}, $id;
push @{$desc{$email}}, $desc;
}
foreach my $email (sort (keys %bugs)) {
my $user = new Bugzilla::User({name => $email});
foreach my $email (sort keys %bugs)
{
my $user = new Bugzilla::User({ name => $email });
next if $user->email_disabled;
my $vars = {'email' => $email};
my $vars = {email => $email};
my @bugs = ();
foreach my $i (@{$bugs{$email}}) {
foreach my $i (@{$bugs{$email}})
{
my $bug = {};
$bug->{'summary'} = shift(@{$desc{$email}});
$bug->{'id'} = $i;
$bug->{summary} = shift(@{$desc{$email}});
$bug->{id} = $i;
push @bugs, $bug;
}
$vars->{'bugs'} = \@bugs;
$vars->{bugs} = \@bugs;
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)
or die($template->error());
|| die($template->error);
Bugzilla->template_inner("");
MessageToMTA($msg);
print "$email " . join(" ", @{$bugs{$email}}) . "\n";
}
exit;