diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index 94f1db77f..f1e256d80 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -3973,7 +3973,7 @@ sub get_ids { return $self->{$fn}; } - elsif ($field && $field->type == FIELD_TYPE_MULTI_SELECT) + elsif ($field && ($field->type == FIELD_TYPE_MULTI_SELECT || $field->type == FIELD_TYPE_BUG_ID_REV)) { return $self->$fn; } @@ -4000,6 +4000,10 @@ sub get_object { $self->{$attr} = $field->value_type->new_from_list($self->$fn); } + elsif ($field && $field->type == FIELD_TYPE_BUG_ID_REV) + { + $self->{$attr} = Bugzilla::Bug->new_from_list($self->$fn); + } else { die "Invalid join requested - ".__PACKAGE__."::$attr"; @@ -4015,15 +4019,19 @@ sub get_string my $f = ref $field ? $field->name : $field; $field = Bugzilla->get_field($field) if !ref $field; my $value; - if ($field->type == FIELD_TYPE_SINGLE_SELECT) + if ($field && $field->type == FIELD_TYPE_SINGLE_SELECT) { $value = $self->get_object($f) && $self->get_object($f)->name; } - elsif ($field->type == FIELD_TYPE_MULTI_SELECT) + elsif ($field && $field->type == FIELD_TYPE_MULTI_SELECT) { $value = join ', ', map { $_->name } @{$self->get_object($f)}; } - elsif ($field->type != FIELD_TYPE_UNKNOWN || SCALAR_FORMAT->{$f}) + elsif ($field && $field->type == FIELD_TYPE_BUG_ID_REV) + { + $value = join ', ', @{ $self->$f }; + } + elsif ($field && $field->type != FIELD_TYPE_UNKNOWN || SCALAR_FORMAT->{$f}) { $value = $self->$f; } @@ -4123,12 +4131,22 @@ sub AUTOLOAD } my $field = Bugzilla->get_field($attr); - if ($field && $field->type == FIELD_TYPE_MULTI_SELECT) + if ($field) { - $self->{$attr} ||= Bugzilla->dbh->selectcol_arrayref( - "SELECT id FROM bug_$attr, $attr WHERE value_id=id AND bug_id=? ORDER BY value", - undef, $self->id); - return $self->{$attr}; + if ($field->type == FIELD_TYPE_MULTI_SELECT) + { + $self->{$attr} ||= Bugzilla->dbh->selectcol_arrayref( + "SELECT id FROM bug_$attr, $attr WHERE value_id=id AND bug_id=? ORDER BY value", + undef, $self->id); + return $self->{$attr}; + } + elsif ($field->type == FIELD_TYPE_BUG_ID_REV) + { + $self->{$attr} ||= Bugzilla->dbh->selectcol_arrayref( + "SELECT bug_id FROM bugs WHERE ".$field->value_field->name." = ".$self->id + ); + return $self->{$attr}; + } } return ''; diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 4440563ad..8b1419e44 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -130,6 +130,7 @@ use Cwd qw(abs_path); FIELD_TYPE_KEYWORDS FIELD_TYPE_NUMERIC FIELD_TYPE_EXTURL + FIELD_TYPE_BUG_ID_REV TIMETRACKING_FIELDS @@ -382,6 +383,7 @@ use constant FIELD_TYPE_KEYWORDS => 8; use constant FIELD_TYPE_NUMERIC => 30; use constant FIELD_TYPE_EXTURL => 31; +use constant FIELD_TYPE_BUG_ID_REV => 32; use constant BUG_ID_ADD_TO_BLOCKED => 1; use constant BUG_ID_ADD_TO_DEPENDSON => 2; diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index f0b8a4944..ed0dfc7ef 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -130,7 +130,7 @@ use constant VALIDATORS => { }; use constant UPDATE_VALIDATORS => { - value_field_id => \&_check_value_field_id, + value_field_id => \&_check_value_field_id, }; use constant UPDATE_COLUMNS => qw( @@ -306,7 +306,7 @@ sub _check_type # higher field type is added. if (!detaint_natural($type) || $type < FIELD_TYPE_UNKNOWN || $type > FIELD_TYPE_KEYWORDS && $type < FIELD_TYPE_NUMERIC || - $type > FIELD_TYPE_EXTURL) + $type > FIELD_TYPE_BUG_ID_REV) { ThrowCodeError('invalid_customfield_type', { type => $saved_type }); } @@ -315,9 +315,27 @@ sub _check_type sub _check_value_field_id { - my ($invocant, $field_id, $is_select) = @_; - $is_select = $invocant->is_select if !defined $is_select; - if ($field_id && !$is_select) + my ($invocant, $field_id, undef, $type) = @_; + $type = $invocant->type if !defined $type; + if ($type == FIELD_TYPE_BUG_ID_REV) + { + # For fields of type "reverse relation of BUG_ID field" + # value_field indicates the needed direct relation + my $field = Bugzilla->get_field(trim($field_id)); + if (!$field || $field->type != FIELD_TYPE_BUG_ID) + { + ThrowUserError('direct_field_needed_for_reverse'); + } + for (Bugzilla->get_fields({ type => FIELD_TYPE_BUG_ID_REV, value_field_id => $field->id })) + { + if (!ref $invocant || $_->id != $invocant->id) + { + ThrowUserError('duplicate_reverse_field'); + } + } + return $field->id; + } + if ($field_id && $type != FIELD_TYPE_SINGLE_SELECT && $type != FIELD_TYPE_MULTI_SELECT) { ThrowUserError('field_value_control_select_only'); } @@ -729,7 +747,7 @@ sub value_field sub value_field_id { my $self = shift; - return undef if !$self->is_select; + return undef if !$self->is_select && $self->type != FIELD_TYPE_BUG_ID_REV; return $self->{value_field_id}; } @@ -930,7 +948,7 @@ sub update # FIXME Merge something like VALIDATOR_DEPENDENCIES from 4.4 if ($self->{type} != FIELD_TYPE_BUG_ID) { - $self->{add_to_deps} = undef; + $self->{add_to_deps} = 0; } if ($self->{type} != FIELD_TYPE_EXTURL) { @@ -1054,15 +1072,12 @@ sub run_create_validators ThrowCodeError('field_type_not_specified'); } - $params->{value_field_id} = $class->_check_value_field_id( - $params->{value_field_id}, - ($type == FIELD_TYPE_SINGLE_SELECT || $type == FIELD_TYPE_MULTI_SELECT) ? 1 : 0 - ); + $params->{value_field_id} = $class->_check_value_field_id($params->{value_field_id}, undef, $type); # FIXME Merge something like VALIDATOR_DEPENDENCIES from 4.4 if ($type != FIELD_TYPE_BUG_ID) { - $params->{add_to_deps} = undef; + $params->{add_to_deps} = 0; } if ($type != FIELD_TYPE_EXTURL) { diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 7a4d99241..a9d04e1f2 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -130,6 +130,7 @@ sub update_fielddefs_definition { $dbh->do('UPDATE fielddefs SET type='.FIELD_TYPE_EXTURL.' WHERE custom=1 AND type=9'); } + # This column is used for fast lookup of fields used in bug history if (!$dbh->bz_column_info('fielddefs', 'has_activity')) { $dbh->bz_add_column('fielddefs', has_activity => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0}); @@ -140,6 +141,26 @@ sub update_fielddefs_definition { ); } + # Migrate reverse_desc (upstream implementation) into separate field objects + if ($dbh->bz_column_info('fielddefs', 'reverse_desc')) + { + my $rows = $dbh->selectall_arrayref( + 'SELECT * FROM fielddefs WHERE custom=1 AND type='.FIELD_TYPE_BUG_ID. + ' AND reverse_desc IS NOT NULL AND reverse_desc != \'\'', {Slice=>{}} + ); + for (@$rows) + { + Bugzilla::Field->create({ + name => $_->{name}.'_rev', + custom => 1, + description => $_->{reverse_desc}, + type => FIELD_TYPE_BUG_ID_REV, + value_field_id => $_->{id}, + }); + } + $dbh->bz_drop_column('fielddefs', 'reverse_desc'); + } + # Remember, this is not the function for adding general table changes. # That is below. Add new changes to the fielddefs table above this # comment. diff --git a/Bugzilla/Language/en.pm b/Bugzilla/Language/en.pm index 58a19652e..f5d46cd90 100644 --- a/Bugzilla/Language/en.pm +++ b/Bugzilla/Language/en.pm @@ -67,13 +67,14 @@ $Bugzilla::messages->{en} = { field_types => { FIELD_TYPE_UNKNOWN() => 'Unknown Type', FIELD_TYPE_FREETEXT() => 'Free Text', - FIELD_TYPE_EXTURL() => 'External URL', FIELD_TYPE_SINGLE_SELECT() => 'Drop Down', FIELD_TYPE_MULTI_SELECT() => 'Multiple-Selection Box', FIELD_TYPE_TEXTAREA() => 'Large Text Box', FIELD_TYPE_DATETIME() => 'Date/Time', FIELD_TYPE_BUG_ID() => $terms->{Bug}.' ID', FIELD_TYPE_NUMERIC() => 'Numeric', + FIELD_TYPE_EXTURL() => 'External URL', + FIELD_TYPE_BUG_ID_REV() => $terms->{Bug}.' ID reverse', }, control_options => { CONTROLMAPNA() => 'NA', diff --git a/js/cf-edit.js b/js/cf-edit.js index 76238d869..2ef21d2ec 100644 --- a/js/cf-edit.js +++ b/js/cf-edit.js @@ -6,11 +6,30 @@ function onChangeType() { var type_field = document.getElementById('type'); var value_field = document.getElementById('value_field_id'); - if (type_field.value == constants.FIELD_TYPE_SINGLE_SELECT - || type_field.value == constants.FIELD_TYPE_MULTI_SELECT) + if (type_field.value == constants.FIELD_TYPE_SINGLE_SELECT || + type_field.value == constants.FIELD_TYPE_MULTI_SELECT) + { value_field.disabled = false; + document.getElementById('value_field_row').style.display = ''; + } else + { value_field.disabled = true; + document.getElementById('value_field_row').style.display = 'none'; + } + var rev_value_field = document.getElementById('bug_id_rev_value_field_id'); + if (type_field.value == constants.FIELD_TYPE_BUG_ID_REV) + { + rev_value_field.name = 'value_field_id'; + value_field.name = ''; + document.getElementById('bug_id_rev_row').style.display = ''; + } + else + { + rev_value_field.name = ''; + value_field.name = 'value_field_id'; + document.getElementById('bug_id_rev_row').style.display = 'none'; + } document.getElementById('add_to_deps').style.display = document.getElementById('add_to_deps_title').style.display = type_field.value == constants.FIELD_TYPE_BUG_ID ? '' : 'none'; diff --git a/template/en/default/admin/custom_fields/edit.html.tmpl b/template/en/default/admin/custom_fields/edit.html.tmpl index 00d4fc315..83b558815 100644 --- a/template/en/default/admin/custom_fields/edit.html.tmpl +++ b/template/en/default/admin/custom_fields/edit.html.tmpl @@ -30,7 +30,8 @@ var constants = { FIELD_TYPE_SINGLE_SELECT: [% constants.FIELD_TYPE_SINGLE_SELECT %], FIELD_TYPE_MULTI_SELECT: [% constants.FIELD_TYPE_MULTI_SELECT %], FIELD_TYPE_BUG_ID: [% constants.FIELD_TYPE_BUG_ID %], - FIELD_TYPE_EXTURL: [% constants.FIELD_TYPE_EXTURL %] + FIELD_TYPE_EXTURL: [% constants.FIELD_TYPE_EXTURL %], + FIELD_TYPE_BUG_ID_REV: [% constants.FIELD_TYPE_BUG_ID_REV %] }; [% END %] @@ -108,7 +109,7 @@ var constants = { [% field_types.${field.type} | html %] [% ELSE %] + + [% FOREACH sel_field = Bugzilla.get_fields({ custom => 1, type => constants.FIELD_TYPE_BUG_ID }) %] + [% NEXT IF sel_field.id == field.id %] + + [% END %] + + + + [% END %] [% IF field.visibility_field %]