WIP BUG_ID reverse relationships (implementation different to upstream)
parent
68ff25fef5
commit
d5e13b4a67
|
@ -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,13 +4131,23 @@ sub AUTOLOAD
|
|||
}
|
||||
|
||||
my $field = Bugzilla->get_field($attr);
|
||||
if ($field && $field->type == FIELD_TYPE_MULTI_SELECT)
|
||||
if ($field)
|
||||
{
|
||||
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 '';
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 %]
|
||||
<select id="type" name="type" onchange="onChangeType()">
|
||||
[% FOREACH type = field_types.keys %]
|
||||
[% FOREACH type = field_types.sort %]
|
||||
[% NEXT IF type == constants.FIELD_TYPE_UNKNOWN %]
|
||||
<option value="[% type | html %]">[% field_types.$type | html %]</option>
|
||||
[% END %]
|
||||
|
@ -183,7 +184,7 @@ var constants = {
|
|||
</tr>
|
||||
[% END %]
|
||||
[% IF field.is_select || !field.id %]
|
||||
<tr valign="top">
|
||||
<tr valign="top" id="value_field_row">
|
||||
<th colspan="2" align="left"><label for="value_field_id">
|
||||
Field that controls the values that appear in this field:
|
||||
</label></th>
|
||||
|
@ -202,6 +203,27 @@ var constants = {
|
|||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% IF field.type == constants.FIELD_TYPE_BUG_ID_REV || !field.id %]
|
||||
<tr valign="top" id="bug_id_rev_row">
|
||||
<th colspan="2" align="left"><label for="bug_id_rev_value_field_id">
|
||||
Direct Bug ID field for this reverse one:
|
||||
</label></th>
|
||||
<td colspan="2">
|
||||
[%# Duplicate name will be cleared by JS on creation form %]
|
||||
<select style="width: 400px" name="value_field_id" id="bug_id_rev_value_field_id">
|
||||
<option value="">---</option>
|
||||
[% FOREACH sel_field = Bugzilla.get_fields({ custom => 1, type => constants.FIELD_TYPE_BUG_ID }) %]
|
||||
[% NEXT IF sel_field.id == field.id %]
|
||||
<option value="[% sel_field.id | html %]"
|
||||
[% ' selected="selected"' IF sel_field.id == field.value_field.id %]>
|
||||
[% sel_field.description | html %]
|
||||
([% sel_field.name | html %])
|
||||
</option>
|
||||
[% END %]
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% IF field.visibility_field %]
|
||||
<tr valign="top" id="visibility_value_row">
|
||||
<th colspan="2" align="left"><label for="visibility_value_id">
|
||||
|
|
|
@ -544,6 +544,20 @@
|
|||
is not the right type of field.
|
||||
[% END %]
|
||||
|
||||
[% BLOCK error_direct_field_needed_for_reverse %]
|
||||
[% title = "Invalid Direct Field selected" %]
|
||||
Each field of type "[% lc_messages.field_types.${constants.FIELD_TYPE_BUG_ID_REV} %]" must correspond
|
||||
to one, and only one field of type "[% lc_messages.field_types.${constants.FIELD_TYPE_BUG_ID} %]" and
|
||||
represent its "reverse relation". For example, it may be "Internal Bugs" for the corresponding
|
||||
"External Bug" field.
|
||||
[% END %]
|
||||
|
||||
[% BLOCK error_duplicate_reverse_field %]
|
||||
[% title = "Duplicate Reverse Field" %]
|
||||
It is prohibited to create more than one field of type "[% lc_messages.field_types.${constants.FIELD_TYPE_BUG_ID_REV} %]"
|
||||
corresponding to a single "[% lc_messages.field_types.${constants.FIELD_TYPE_BUG_ID} %]" type field.
|
||||
[% END %]
|
||||
|
||||
[% BLOCK error_field_type_mismatch %]
|
||||
Cannot seem to handle <code>[% field FILTER html %]</code>
|
||||
and <code>[% type FILTER html %]</code> together.
|
||||
|
|
Loading…
Reference in New Issue