diff --git a/Bugzilla.pm b/Bugzilla.pm index 66c199c0b..634854f20 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -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; diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index a95921001..ffdfbf4fc 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -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 diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index 389abbd00..eb87d1396 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -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}; } diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index c1f3e0e49..f896a55d5 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -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}} }; diff --git a/Bugzilla/Field/Choice.pm b/Bugzilla/Field/Choice.pm index 35d4d70e8..89d23a826 100644 --- a/Bugzilla/Field/Choice.pm +++ b/Bugzilla/Field/Choice.pm @@ -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 { diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 0f1329156..7f08e4970 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -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 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 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 diff --git a/editfields.cgi b/editfields.cgi index 99926cca1..34697241b 100755 --- a/editfields.cgi +++ b/editfields.cgi @@ -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. diff --git a/editvalues.cgi b/editvalues.cgi index 0b17b4c34..b9b058b9b 100755 --- a/editvalues.cgi +++ b/editvalues.cgi @@ -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); diff --git a/js/bug-visibility.js b/js/bug-visibility.js index 2e54d2f09..c5c5118a5 100644 --- a/js/bug-visibility.js +++ b/js/bug-visibility.js @@ -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); diff --git a/template/en/default/admin/custom_fields/edit.html.tmpl b/template/en/default/admin/custom_fields/edit.html.tmpl index 9201b2927..8f6523162 100644 --- a/template/en/default/admin/custom_fields/edit.html.tmpl +++ b/template/en/default/admin/custom_fields/edit.html.tmpl @@ -113,6 +113,21 @@ var constants = { [% END %] + [% IF field.id %] + Default value: + + [% IF field.is_select %] + + [% ELSE %] + + [% END %] + + [% END %] [% IF field.type && field.type != constants.FIELD_TYPE_BUG_ID_REV || !field.id %] diff --git a/template/en/default/admin/fieldvalues/control-list.html.tmpl b/template/en/default/admin/fieldvalues/control-list.html.tmpl index b30b7bae9..82929bcd5 100644 --- a/template/en/default/admin/fieldvalues/control-list.html.tmpl +++ b/template/en/default/admin/fieldvalues/control-list.html.tmpl @@ -37,12 +37,23 @@

Значения [% field.description FILTER html %] для [% field_value.name FILTER html %]:

+

Значение по умолчанию:[% "
" IF field.type == constants.FIELD_TYPE_MULTI_SELECT %] + [% IF field.is_select %] + +

+ [% ELSE %] + + [% END %] - [% count = 0 %] @@ -60,11 +71,6 @@ [% END %] -
Значение АктивноПо умолчанию
- - [% IF value.visible_for_all() %] Значение видимо для всех значений поля [% field.value_field.description FILTER html %]
@@ -92,37 +98,5 @@ К списку значений [% field.description FILTER html %] - - [% PROCESS global/footer.html.tmpl %]