Remove non-hash Bugzilla->fieldvaluecontrol, move dependent default values into a separate table, simplify bz_add_column

hinted-selects
Vitaliy Filippov 2014-06-30 19:31:24 +04:00
parent 4f20f1242c
commit 74ecc3d2c5
11 changed files with 233 additions and 242 deletions

View File

@ -932,13 +932,13 @@ sub fieldvaluecontrol
my $cache = $class->cache_fields;
if (!$cache->{fieldvaluecontrol})
{
$cache->{fieldvaluecontrol} = $class->dbh->selectall_arrayref(
my $rows = $class->dbh->selectall_arrayref(
'SELECT c.*, (CASE WHEN c.value_id <= 0 THEN f.visibility_field_id ELSE f.value_field_id END) visibility_field_id'.
' FROM fieldvaluecontrol c, fielddefs f WHERE f.id=c.field_id'.
' ORDER BY c.field_id, c.value_id, (CASE WHEN c.value_id=0 THEN f.visibility_field_id ELSE f.value_field_id END), c.visibility_value_id', {Slice=>{}}
);
my $has = {};
for (@{$cache->{fieldvaluecontrol}})
for (@$rows)
{
if ($_->{value_id} > 0)
{
@ -947,8 +947,7 @@ sub fieldvaluecontrol
->{values}
->{$_->{field_id}}
->{$_->{value_id}}
->{$_->{visibility_value_id}}
->{is_default} = $_->{is_default};
->{$_->{visibility_value_id}} = 1;
}
elsif (!$_->{value_id})
{
@ -967,22 +966,24 @@ sub fieldvaluecontrol
->{$_->{visibility_value_id}} = 1;
}
}
$cache->{fieldvaluecontrol_hash} = $has;
# Dependent defaults
$rows = $class->dbh->selectall_arrayref(
# FIXME: it will be default_field_id
'SELECT d.field_id, f.visibility_field_id, d.visibility_value_id, d.default_value'.
' FROM field_defaults d, fielddefs f WHERE f.id=d.field_id', {Slice=>{}}
);
for (@$rows)
{
$has->{$_->{visibility_field_id}}
->{defaults}
->{$_->{field_id}}
->{$_->{visibility_value_id}} = $_->{default_value};
}
$cache->{fieldvaluecontrol} = $has;
}
return $cache->{fieldvaluecontrol};
}
sub fieldvaluecontrol_hash
{
my $class = shift;
my $cache = $class->cache_fields;
if (!$cache->{fieldvaluecontrol_hash})
{
$class->fieldvaluecontrol;
}
return $cache->{fieldvaluecontrol_hash};
}
sub full_json_visibility
{
my $class = shift;

View File

@ -538,6 +538,14 @@ sub bz_drop_foreign_keys {
sub bz_add_column {
my ($self, $table, $name, $new_def, $init_value) = @_;
if (!$new_def) {
# Take default definition from schema, but exclude REFERENCES
$new_def = $self->_bz_schema->get_column_abstract($table, $name)
|| die "bz_add_column: unknown column $table.$name";
$new_def = { %$new_def };
delete $new_def->{REFERENCES};
}
# You can't add a NOT NULL column to a table with
# no DEFAULT statement, unless you have an init_value.
# SERIAL types are an exception, though, because they can

View File

@ -549,27 +549,24 @@ use constant ABSTRACT_SCHEMA => {
fielddefs => {
FIELDS => [
id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1},
name => {TYPE => 'varchar(255)', NOTNULL => 1},
type => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => FIELD_TYPE_UNKNOWN},
custom => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
description => {TYPE => 'TINYTEXT', NOTNULL => 1},
mailhead => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
sortkey => {TYPE => 'INT2', NOTNULL => 1},
obsolete => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
clone_bug => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
is_mandatory => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1},
name => {TYPE => 'varchar(255)', NOTNULL => 1},
type => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => FIELD_TYPE_UNKNOWN},
custom => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
description => {TYPE => 'TINYTEXT', NOTNULL => 1},
mailhead => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
sortkey => {TYPE => 'INT2', NOTNULL => 1},
obsolete => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
clone_bug => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
is_mandatory => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'},
url => {TYPE => 'VARCHAR(255)'}, # template for FIELD_TYPE_EXTURL
delta_ts => {TYPE => 'DATETIME'}, # for refreshing client-side cache
has_activity => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0},
add_to_deps => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0}, # for FIELD_TYPE_BUG_ID
default_value => {TYPE => 'MEDIUMTEXT'},
# Fields that change the behaviour of this one in various ways
visibility_field_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'fielddefs', COLUMN => 'id'}},
# CustIS Bug 53617 - visibility_value_id is removed from here
# (migrated to fieldvaluecontrol table)
value_field_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'fielddefs', COLUMN => 'id'}},
# Used for "external link via template" type fields (CustIS Bug 90854)
url => {TYPE => 'VARCHAR(255)'},
# Used for refreshing client-side field/value cache (CustIS Bug 70605)
delta_ts => {TYPE => 'DATETIME'},
has_activity => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0},
# Automatic addition of Bug ID field value dependencies (CustIS Bug 73054)
add_to_deps => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0},
value_field_id => {TYPE => 'INT4', REFERENCES => {TABLE => 'fielddefs', COLUMN => 'id'}},
],
INDEXES => [
fielddefs_name_idx => {FIELDS => ['name'], TYPE => 'UNIQUE'},
@ -578,6 +575,18 @@ use constant ABSTRACT_SCHEMA => {
],
},
# Default values
field_defaults => {
FIELDS => [
field_id => {TYPE => 'INT4', NOTNULL => 1},
visibility_value_id => {TYPE => 'INT4', NOTNULL => 1},
default_value => {TYPE => 'MEDIUMTEXT', NOTNULL => 1},
],
INDEXES => [
fieldvaluecontrol_primary_idx => {FIELDS => ['field_id', 'visibility_value_id'], TYPE => 'PRIMARY'},
],
},
# All value/value and value/field dependencies are stored here
# value_id > 0: value with this id is visible if value field has value visibility_value_id
# value_id == 0: field is visible if visibility field has value visibility_value_id
@ -588,7 +597,6 @@ use constant ABSTRACT_SCHEMA => {
field_id => {TYPE => 'INT4', NOTNULL => 1},
value_id => {TYPE => 'INT4', NOTNULL => 1},
visibility_value_id => {TYPE => 'INT4', NOTNULL => 1},
is_default => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0},
],
INDEXES => [
fieldvaluecontrol_primary_idx => {FIELDS => ['field_id', 'visibility_value_id', 'value_id'], TYPE => 'UNIQUE'},
@ -2099,6 +2107,7 @@ sub get_column_abstract {
# Prevent a possible dereferencing of an undef hash, if the
# table doesn't exist.
if ($self->get_table_abstract($table)) {
# FIXME This hash is recreated each time you call get_column_abstract... :-(
my %fields = (@{ $self->{abstract_schema}{$table}{FIELDS} });
return $fields{$column};
}

View File

@ -102,12 +102,13 @@ use constant DB_COLUMNS => qw(
obsolete
is_mandatory
clone_bug
visibility_field_id
value_field_id
delta_ts
has_activity
add_to_deps
url
default_value
visibility_field_id
value_field_id
);
use constant REQUIRED_CREATE_FIELDS => qw(name description);
@ -126,24 +127,11 @@ use constant VALIDATORS => {
};
use constant UPDATE_VALIDATORS => {
value_field_id => \&_check_value_field_id,
value_field_id => \&_check_value_field_id,
default_value => \&_check_default_value,
};
use constant UPDATE_COLUMNS => qw(
description
mailhead
sortkey
obsolete
is_mandatory
clone_bug
visibility_field_id
value_field_id
type
delta_ts
has_activity
add_to_deps
url
);
use constant UPDATE_COLUMNS => grep { $_ ne 'type' && $_ ne 'id' } DB_COLUMNS();
# How various field types translate into SQL data definitions.
use constant SQL_DEFINITIONS => {
@ -373,6 +361,28 @@ sub _check_add_to_deps
return $addto{$value || ''};
}
sub _check_default_value
{
my ($self, $value) = @_;
if ($self->type == FIELD_TYPE_SINGLE_SELECT)
{
# ID
detaint_natural($value) || undef;
}
elsif ($self->type == FIELD_TYPE_MULTI_SELECT)
{
# Array of IDs
$value = [ $value ] if !ref $value;
detaint_natural($_) for @$value;
$value = @$value ? join(',', @$value) : undef;
}
elsif ($self->type == FIELD_TYPE_BUG_ID_REV)
{
return undef;
}
return $value;
}
=pod
=head2 Instance Properties
@ -521,6 +531,10 @@ sub add_to_deps { $_[0]->type == FIELD_TYPE_BUG_ID && $_[0]->{add_to_deps} }
sub url { $_[0]->{url} }
sub default_value { $_[0]->{default_value} }
sub default_value_hash { $_[0]->is_select ? { map { $_ => 1 } split /,/, $_[0]->{default_value} } : undef }
sub value_type
{
my $self = shift;
@ -567,7 +581,7 @@ sub restricted_legal_values
my $rc_cache = Bugzilla->rc_cache_fields;
if (!$rc_cache->{$self}->{restricted_legal_values}->{$controller_value})
{
my $hash = Bugzilla->fieldvaluecontrol_hash->{$self->value_field_id}->{values}->{$self->id};
my $hash = Bugzilla->fieldvaluecontrol->{$self->value_field_id}->{values}->{$self->id};
$rc_cache->{$self}->{restricted_legal_values}->{$controller_value} = [
grep {
$_->is_static || !exists $hash->{$_->id} ||
@ -578,29 +592,6 @@ sub restricted_legal_values
return $rc_cache->{$self}->{restricted_legal_values}->{$controller_value};
}
# Select default values for a named value of controlling field
sub get_default_values
{
my $self = shift;
my ($controller_value) = @_;
return [] unless $self->value_field;
my @values;
my $field_values = $self->value_field->legal_values;
foreach my $field_value (@$field_values)
{
if ($field_value->{name} eq $controller_value)
{
my $cvalues = $self->legal_values;
foreach my $value (@$cvalues)
{
push @values, $value->{value} if $value->is_default_controlled_value($field_value->{id}) && !$value->is_static;
}
last;
}
}
return \@values;
}
=pod
=over
@ -636,7 +627,7 @@ sub visibility_values
{
my $self = shift;
return undef if !$self->visibility_field_id;
my $h = Bugzilla->fieldvaluecontrol_hash
my $h = Bugzilla->fieldvaluecontrol
->{$self->visibility_field_id}->{fields}->{$self->id};
return $h && %$h ? $h : undef;
}
@ -647,7 +638,7 @@ sub has_visibility_value
return 1 if !$self->visibility_field_id;
my ($value) = @_;
$value = $value->id if ref $value;
my $hash = Bugzilla->fieldvaluecontrol_hash
my $hash = Bugzilla->fieldvaluecontrol
->{$self->visibility_field_id}->{fields}->{$self->id};
return !$hash || !%$hash || $hash->{$value};
}
@ -656,7 +647,7 @@ sub null_visibility_values
{
my $self = shift;
return undef if !$self->visibility_field_id;
my $h = Bugzilla->fieldvaluecontrol_hash
my $h = Bugzilla->fieldvaluecontrol
->{$self->visibility_field_id}->{null}->{$self->id};
return $h && %$h ? $h : undef;
}
@ -785,14 +776,15 @@ They will throw an error if you try to set the values to something invalid.
=cut
sub set_description { $_[0]->set('description', $_[1]); }
sub set_clone_bug { $_[0]->set('clone_bug', $_[1]); }
sub set_obsolete { $_[0]->set('obsolete', $_[1]); }
sub set_is_mandatory { $_[0]->set('is_mandatory', $_[1]); }
sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
sub set_in_new_bugmail { $_[0]->set('mailhead', $_[1]); }
sub set_add_to_deps { $_[0]->set('add_to_deps', $_[1]); }
sub set_url { $_[0]->set('url', $_[1]); }
sub set_description { $_[0]->set('description', $_[1]); }
sub set_clone_bug { $_[0]->set('clone_bug', $_[1]); }
sub set_obsolete { $_[0]->set('obsolete', $_[1]); }
sub set_is_mandatory { $_[0]->set('is_mandatory', $_[1]); }
sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
sub set_in_new_bugmail { $_[0]->set('mailhead', $_[1]); }
sub set_add_to_deps { $_[0]->set('add_to_deps', $_[1]); }
sub set_url { $_[0]->set('url', $_[1]); }
sub set_default_value { $_[0]->set('default_value', $_[1]); }
sub set_visibility_field
{
@ -1064,6 +1056,13 @@ sub run_create_validators
$params->{url} = undef;
}
# Check default value
if ($type == FIELD_TYPE_SINGLE_SELECT || $type == FIELD_TYPE_MULTI_SELECT ||
$type == FIELD_TYPE_BUG_ID || $type == FIELD_TYPE_BUG_ID_REV)
{
$params->{default_value} = undef;
}
return $params;
}
@ -1324,7 +1323,7 @@ sub toggle_value
sub update_controlled_values
{
my ($controlled_field, $controlled_value_ids, $visibility_value_id, $default_value_ids) = @_;
my ($controlled_field, $controlled_value_ids, $visibility_value_id) = @_;
$controlled_value_ids ||= [];
my $vis_field = $controlled_field->value_field;
if (!$vis_field)
@ -1333,11 +1332,6 @@ sub update_controlled_values
}
$controlled_field = Bugzilla->get_field($controlled_field) if !ref $controlled_field;
$visibility_value_id = int($visibility_value_id);
if ($visibility_value_id)
{
my $type = Bugzilla::Field::Choice->type($vis_field);
$visibility_value_id = $type->new($visibility_value_id)->{id};
}
Bugzilla->dbh->do(
"DELETE FROM fieldvaluecontrol WHERE field_id=? AND visibility_value_id=? AND value_id!=0",
undef, $controlled_field->id, $visibility_value_id);
@ -1345,13 +1339,9 @@ sub update_controlled_values
{
my $type = Bugzilla::Field::Choice->type($controlled_field);
$controlled_value_ids = [ map { $_->id } @{ $type->new_from_list($controlled_value_ids) } ];
if ($default_value_ids)
{
$default_value_ids = { map { $_->id => 1 } @{ $type->new_from_list($default_value_ids) } };
}
my $f = $controlled_field->id;
my $sql = "INSERT INTO fieldvaluecontrol (field_id, visibility_value_id, value_id, is_default) VALUES ".
join(",", map { "($f, $visibility_value_id, $_, " . ($default_value_ids->{$_} ? '1' : '0') . ')' } @$controlled_value_ids);
my $sql = "INSERT INTO fieldvaluecontrol (field_id, visibility_value_id, value_id) VALUES ".
join(",", map { "($f, $visibility_value_id, $_)" } @$controlled_value_ids);
Bugzilla->dbh->do($sql);
}
# Touch the field
@ -1361,15 +1351,24 @@ sub update_controlled_values
sub update_default_values
{
my ($controlled_field, $visibility_value_id, $default_value_ids) = @_;
my ($controlled_field, $visibility_value_id, $default_value) = @_;
$controlled_field = Bugzilla->get_field($controlled_field) if !ref $controlled_field;
$visibility_value_id = int($visibility_value_id);
$default_value_ids = [ map { int $_ } @$default_value_ids || (0) ];
Bugzilla->dbh->do(
'UPDATE fieldvaluecontrol SET is_default=(value_id IN ('.join(', ', @$default_value_ids).
')) WHERE field_id=? AND visibility_value_id=? AND value_id!=0',
undef, $controlled_field->id, $visibility_value_id
);
$default_value = $controlled_field->_check_default_value($default_value);
if (!$default_value)
{
Bugzilla->dbh->do(
'DELETE FROM field_defaults WHERE field_id=? AND visibility_value_id=?',
undef, $controlled_field->id, $visibility_value_id
);
}
else
{
Bugzilla->dbh->do(
'REPLACE INTO field_defaults (field_id, visibility_value_id, default_value) VALUES (?, ?, ?)',
undef, $controlled_field->id, $visibility_value_id, $default_value
);
}
# Touch the field
$controlled_field->touch;
return 1;
@ -1388,7 +1387,7 @@ sub json_visibility
values => {},
null => {},
};
my $hash = Bugzilla->fieldvaluecontrol_hash->{$self->id};
my $hash = Bugzilla->fieldvaluecontrol->{$self->id};
for my $key (qw(fields values null))
{
$data->{$key} = { map { Bugzilla->get_field($_)->name => $hash->{$key}->{$_} } keys %{$hash->{$key}} };

View File

@ -235,7 +235,7 @@ sub get_all
# Product field is a special case: it has access controls applied.
# So if our values are controlled by product field value,
# return only ones visible inside products visible to current user.
my $h = Bugzilla->fieldvaluecontrol_hash
my $h = Bugzilla->fieldvaluecontrol
->{Bugzilla->get_field('product')->id}
->{values}
->{$f->id};
@ -381,11 +381,9 @@ sub controls_visibility_of_fields
my $vid = $self->id;
my $fid = $self->field->id;
$self->{controls_visibility_of_fields} ||= [
map { Bugzilla->get_field($_->{field_id}) }
grep { !$_->{value_id} &&
$_->{visibility_value_id} == $vid &&
$_->{visibility_field_id} == $fid }
@{Bugzilla->fieldvaluecontrol}
map { Bugzilla->get_field($_) }
grep { Bugzilla->fieldvaluecontrol->{$fid}->{fields}->{$_}->{$vid} }
keys %{Bugzilla->fieldvaluecontrol->{$fid}->{fields}}
];
return $self->{controls_visibility_of_fields};
}
@ -397,20 +395,15 @@ sub controls_visibility_of_field_values
my $fid = $self->field->id;
if (!$self->{controls_visibility_of_field_values})
{
my $h = Bugzilla->fieldvaluecontrol->{$fid}->{values};
my $r = {};
for (@{Bugzilla->fieldvaluecontrol})
for my $f (keys %$h)
{
if ($_->{value_id} &&
$_->{visibility_value_id} == $vid &&
$_->{visibility_field_id} == $fid)
{
push @{$r->{$_->{field_id}}}, $_->{value_id};
}
my $t = [ grep { $h->{$f}->{$_}->{$vid} } keys %{$h->{$f}} ];
$f = Bugzilla->get_field($f);
$r->{$f->name} = $f->value_type->new_from_list($t) if @$t;
}
$self->{controls_visibility_of_field_values} = { map {
Bugzilla->get_field($_)->name =>
Bugzilla::Field::Choice->type(Bugzilla->get_field($_))->new_from_list($r->{$_})
} keys %$r };
$self->{controls_visibility_of_field_values} = $r;
}
return $self->{controls_visibility_of_field_values};
}
@ -421,7 +414,7 @@ sub visibility_values
my $f;
if ($self->field->value_field_id && !($f = $self->{visibility_values}))
{
my $hash = Bugzilla->fieldvaluecontrol_hash
my $hash = Bugzilla->fieldvaluecontrol
->{$self->field->value_field_id}
->{values}
->{$self->field->id}
@ -444,7 +437,7 @@ sub has_visibility_value
$default = 1 if !defined $default;
return $default if !$self->field->value_field_id;
$value = $value->id if ref $value;
my $hash = Bugzilla->fieldvaluecontrol_hash
my $hash = Bugzilla->fieldvaluecontrol
->{$self->field->value_field_id}
->{values}
->{$self->field->id}
@ -459,7 +452,7 @@ sub visible_for_all
my ($default) = @_;
$default = 0 if !defined $default;
return $default if !$self->field->value_field_id;
my $hash = Bugzilla->fieldvaluecontrol_hash
my $hash = Bugzilla->fieldvaluecontrol
->{$self->field->value_field_id}
->{values}
->{$self->field->id}
@ -467,14 +460,6 @@ sub visible_for_all
return !$hash || !%$hash;
}
sub is_default_controlled_value
{
my $self = shift;
my $result = $self->has_visibility_value(@_);
return $result unless ref $result;
return $result->{is_default};
}
# Check visibility of field value for a bug or a hashref with default value names
sub check_visibility
{

View File

@ -37,7 +37,8 @@ use Time::HiRes qw(time);
# NOTE: This is NOT the function for general table updates. See
# update_table_definitions for that. This is only for the fielddefs table.
sub update_fielddefs_definition {
sub update_fielddefs_definition
{
my $dbh = Bugzilla->dbh;
# 2005-02-21 - LpSolit@gmail.com - Bug 279910
@ -46,61 +47,50 @@ sub update_fielddefs_definition {
# table should therefore be marked as obsolete, meaning that they cannot
# be used anymore when querying the database - they are not deleted in
# order to keep track of these fields in the activity table.
if (!$dbh->bz_column_info('fielddefs', 'obsolete')) {
$dbh->bz_add_column('fielddefs', 'obsolete',
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
print "Marking qacontact_accessible and assignee_accessible as",
" obsolete fields...\n";
$dbh->do("UPDATE fielddefs SET obsolete = 1
WHERE name = 'qacontact_accessible'
OR name = 'assignee_accessible'");
if (!$dbh->bz_column_info('fielddefs', 'obsolete'))
{
$dbh->bz_add_column('fielddefs', 'obsolete');
print "Marking qacontact_accessible and assignee_accessible as obsolete fields...\n";
$dbh->do("UPDATE fielddefs SET obsolete=1 WHERE name IN ('qacontact_accessible', 'assignee_accessible')");
}
# 2005-08-10 Myk Melez <myk@mozilla.org> bug 287325
# Record each field's type and whether or not it's a custom field,
# in fielddefs.
$dbh->bz_add_column('fielddefs', 'type',
{TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0});
$dbh->bz_add_column('fielddefs', 'custom',
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
# Change the name of the fieldid column to id, so that fielddefs
# can use Bugzilla::Object easily. We have to do this up here, because
# otherwise adding these field definitions will fail.
$dbh->bz_rename_column('fielddefs', 'fieldid', 'id');
# 2005-08-10 Myk Melez <myk@mozilla.org> bug 287325
# Record each field's type and whether or not it's a custom field,
# in fielddefs.
# Add columns that don't require special logic
for my $c (qw(type custom clone_bug url is_mandatory add_to_deps default_value
visibility_field_id value_field_id))
{
$dbh->bz_add_column('fielddefs', $c);
}
$dbh->bz_add_index('fielddefs', 'fielddefs_value_field_id_idx', ['value_field_id']);
# If the largest fielddefs sortkey is less than 100, then
# we're using the old sorting system, and we should convert
# it to the new one before adding any new definitions.
if (!$dbh->selectrow_arrayref(
'SELECT COUNT(id) FROM fielddefs WHERE sortkey >= 100'))
if (!$dbh->selectrow_arrayref('SELECT COUNT(id) FROM fielddefs WHERE sortkey >= 100'))
{
print "Updating the sortkeys for the fielddefs table...\n";
my $field_ids = $dbh->selectcol_arrayref(
'SELECT id FROM fielddefs ORDER BY sortkey');
my $field_ids = $dbh->selectcol_arrayref('SELECT id FROM fielddefs ORDER BY sortkey');
my $sortkey = 100;
foreach my $field_id (@$field_ids) {
$dbh->do('UPDATE fielddefs SET sortkey = ? WHERE id = ?',
undef, $sortkey, $field_id);
foreach my $field_id (@$field_ids)
{
$dbh->do('UPDATE fielddefs SET sortkey = ? WHERE id = ?', undef, $sortkey, $field_id);
$sortkey += 100;
}
}
$dbh->bz_add_column('fielddefs', 'visibility_field_id', {TYPE => 'INT4'});
# visibility_value_id is not added anymore during update - it's now in fieldvaluecontrol
$dbh->bz_add_column('fielddefs', 'value_field_id', {TYPE => 'INT4'});
$dbh->bz_add_index('fielddefs', 'fielddefs_value_field_id_idx',
['value_field_id']);
$dbh->bz_add_column('fielddefs', clone_bug => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 1});
$dbh->bz_add_column('fielddefs', url => {TYPE => 'VARCHAR(255)'});
$dbh->bz_add_column('fielddefs', is_mandatory => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
if ($dbh->bz_column_info('fielddefs', 'nullable'))
{
$dbh->do('UPDATE fielddefs SET is_mandatory=NOT nullable');
$dbh->bz_drop_column('fielddefs', 'nullable');
}
$dbh->bz_add_column('fielddefs', add_to_deps => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0});
if (!$dbh->bz_column_info('fielddefs', 'delta_ts'))
{
@ -804,20 +794,25 @@ WHERE description LIKE\'%[CC:%\'');
$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');
# Copy products.defaultmilestone information into fieldvaluecontrol
my $fid = Bugzilla->get_field('target_milestone')->id;
if ($fid && $dbh->selectrow_array(
"SELECT defaultmilestone FROM products p, fieldvaluecontrol c".
" WHERE c.field_id=$fid AND c.value_id=p.defaultmilestone".
" AND c.visibility_value_id=p.id AND NOT c.is_default"
))
# Move fieldvaluecontrol.is_default to field_defaults
if ($dbh->bz_column_info(fieldvaluecontrol => 'is_default'))
{
print "Copying default milestone information into fieldvaluecontrol table...\n";
$dbh->do("UPDATE fieldvaluecontrol c SET c.is_default=0 WHERE c.field_id=$fid AND c.value_id!=0");
$dbh->do(
"UPDATE fieldvaluecontrol c, products p SET c.is_default=1".
" WHERE c.field_id=$fid AND c.value_id=p.defaultmilestone".
" AND c.visibility_value_id=p.id AND NOT c.is_default"
"INSERT INTO field_defaults (field_id, visibility_value_id, default_value)".
" SELECT field_id, visibility_value_id, ".$dbh->sql_group_concat('value_id', "','").
" FROM fieldvaluecontrol WHERE is_default=1"
);
$dbh->bz_drop_column(fieldvaluecontrol => 'is_default');
}
# Copy products.defaultmilestone information into field_defaults
my $fid = Bugzilla->get_field('target_milestone')->id;
if ($fid && $dbh->selectrow_array("SELECT * FROM field_defaults WHERE field_id=$fid"))
{
print "Copying default milestone information into field_defaults...\n";
$dbh->do(
"INSERT INTO field_defaults (field_id, visibility_value_id, default_value)".
" SELECT $fid, id, defaultmilestone FROM products"
);
}
@ -3882,9 +3877,6 @@ sub _make_fieldvaluecontrol
{
my ($dbh) = @_;
# Dependent default values for custom fields (CustIS Bug 91153)
$dbh->bz_add_column('fieldvaluecontrol', is_default => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0});
if ($dbh->bz_column_info('fielddefs', 'visibility_value_id'))
{
# Move 3.x visibility_value_id of standard fields to fieldvaluecontrol

View File

@ -106,12 +106,13 @@ elsif ($action eq 'update')
my $field = Bugzilla->get_field($name);
$field || ThrowUserError('customfield_nonexistent', {'name' => $name});
$field->set_description($cgi->param('desc'));
$field->set_sortkey($cgi->param('sortkey'));
$field->set_in_new_bugmail($cgi->param('new_bugmail'));
$field->set_obsolete($cgi->param('obsolete'));
$field->set_description(scalar $cgi->param('desc'));
$field->set_sortkey(scalar $cgi->param('sortkey'));
$field->set_in_new_bugmail(scalar $cgi->param('new_bugmail'));
$field->set_obsolete(scalar $cgi->param('obsolete'));
$field->set_is_mandatory(!scalar $cgi->param('nullable'));
$field->set_url($cgi->param('url'));
$field->set_url(scalar $cgi->param('url'));
$field->set_default_value($field->type == FIELD_TYPE_MULTI_SELECT ? [ $cgi->param('default_value') ] : scalar $cgi->param('default_value'));
if ($field->custom)
{
# TODO enter_bug could be edited for non-custom fields, too.

View File

@ -126,14 +126,17 @@ if ($action eq 'control_list')
my $step = $ARGS->{step} || 0;
my $visibility_value_id = $ARGS->{visibility_value_id};
$visibility_value_id = Bugzilla::Field::Choice->type($field->value_field)->new($visibility_value_id)->{id};
my $values = $ARGS->{values};
my $default_value_id = $ARGS->{default_value_id};
my $need_token = 0;
$vars->{visibility_value_id} = -1;
if ($visibility_value_id)
{
$vars->{visibility_value_id} = $visibility_value_id;
$vars->{default_value_hash} = { map { $_ => 1 } split /,/, Bugzilla->fieldvaluecontrol
->{$field->value_field_id}->{defaults}->{$field->id}->{$visibility_value_id} };
my %values = map { $_->{id} => $_ } @{$field->{value_field}->legal_values()};
$vars->{field_value} = $values{$visibility_value_id};
$step++ unless $token;
@ -141,7 +144,10 @@ if ($action eq 'control_list')
if ($token)
{
check_token_data($token, "edit_control_list");
$field->update_controlled_values($values, $visibility_value_id, $default_value_id);
$field->update_controlled_values($values, $visibility_value_id);
$field->update_default_values($visibility_value_id, $field->type == FIELD_TYPE_MULTI_SELECT
? [ $cgi->param('default_value') ]
: scalar $cgi->param('default_value'));
$step++;
$need_token = 0;
delete_token($token);

View File

@ -43,26 +43,27 @@ function initControllerField(i)
}
// Select default value in each controlled field
for (var controlled_id in show_fields[f.id]['values'])
for (var controlled_id in show_fields[f.id]['defaults'])
{
var controlled = document.getElementById(controlled_id);
if (!controlled)
{
continue;
}
var vals = show_fields[f.id]['values'][controlled_id];
for (var value_id in vals)
var v = show_fields[f.id]['defaults'][controlled_id];
if (controlled.nodeName == 'SELECT')
{
if (!vals[value_id][control_id])
for (var i in v)
{
continue;
}
if (vals[value_id][control_id].is_default == 1)
{
document.getElementById('v' + value_id + '_' + controlled_id).selected = true;
i = document.getElementById('v' + v[i] + '_' + controlled_id);
if (i)
i.selected = true;
}
}
else
{
controlled.value = v;
}
}
}
handleControllerField(document.forms['Create'] ? null : 'INITIAL', f);

View File

@ -113,6 +113,21 @@ var constants = {
</select>
[% END %]
</td>
[% IF field.id %]
<th align="left" id="default_value_th">Default value:</th>
<td id="default_value_td">
[% IF field.is_select %]
<select name="default_value" style="width: 400px" [% "multiple size=3" IF field.type == constants.FIELD_TYPE_MULTI_SELECT %]>
<option value="">---</option>
[% FOREACH v = field.legal_values %]
<option value="[% v.id | html %]"[% " selected" IF field.default_value_hash.${v.id} %]>[% v.name | html %]</option>
[% END %]
</select>
[% ELSE %]
<input type="text" name="default_value" value="[% field.default_value | html %]" style="width: 400px" />
[% END %]
</td>
[% END %]
</tr>
[% IF field.type && field.type != constants.FIELD_TYPE_BUG_ID_REV || !field.id %]
<tr valign="top">

View File

@ -37,12 +37,23 @@
<input type="hidden" name="step" value="[% step FILTER html %]"/>
<input type="hidden" name="visibility_value_id" value="[% visibility_value_id FILTER html %]"/>
<p>Значения <strong>[% field.description FILTER html %]</strong> для <strong>[% field_value.name FILTER html %]</strong>:</p>
<p>Значение по умолчанию:[% "<br />" IF field.type == constants.FIELD_TYPE_MULTI_SELECT %]
[% IF field.is_select %]
<select name="default_value" style="width: 400px" [% "multiple size=3" IF field.type == constants.FIELD_TYPE_MULTI_SELECT %]>
<option value="">---</option>
[% FOREACH v = field.legal_values %]
<option value="[% v.id | html %]"[% " selected" IF default_value_hash.${v.id} %]>[% v.name | html %]</option>
[% END %]
</select>
</p>
[% ELSE %]
<input type="text" name="default_value" value="[% field.default_value | html %]" style="width: 400px" />
[% END %]
<table id="admin_table" cellpadding="4">
<tbody>
<tr>
<th align="left">Значение</th>
<th align="left">Активно</th>
<th align="left">По умолчанию</th>
<th></th>
</tr>
[% count = 0 %]
@ -60,11 +71,6 @@
<input type="checkbox" id="val_[% value.id %]" value="[% value.id %]" name="values[]" onchange="changeDefaultEnabling(this);"[% ' checked="checked"' IF value.has_visibility_value(field_value.id, 0) %]/>
[% END %]
</td>
<td align="center">
<input type="[% (field.type == constants.FIELD_TYPE_MULTI_SELECT ? 'checkbox' : 'radio') %]"
id="def_val_[% value.id %]" value="[% value.id %]"
name="default_value_id[]"[% ' checked="checked"' IF value.is_default_controlled_value(field_value.id, 0) %]/>
</td>
<td>
[% IF value.visible_for_all() %]
Значение видимо для всех значений поля <strong>[% field.value_field.description FILTER html %]</strong><br/>
@ -92,37 +98,5 @@
<a href="editvalues.cgi?field=
[%- field.name FILTER url_quote %]">К списку значений <strong>[% field.description FILTER html %]</strong></a>
</form>
<script type="text/javascript">
function clearDefault()
{
var elems = document.forms['setValuesForm'].elements['default_value_id'];
for (var i in elems)
{
elems[i].checked = false;
}
}
function changeDefaultEnabling(self)
{
var id = self.id.substr('val_'.length);
var elem = document.getElementById('def_val_' + id);
if (elem)
{
if ((elem.disabled = !self.checked) && elem.checked)
{
elem.checked = false;
}
}
}
var checkboxes = document.forms['setValuesForm'].elements['values[]'];
for (var i in checkboxes)
{
if (!checkboxes[i].tagName) continue;
if (checkboxes[i].tagName.toLowerCase() != 'input') continue;
changeDefaultEnabling(checkboxes[i]);
}
</script>
[% PROCESS global/footer.html.tmpl %]