"Large Text Box (separate table)" field type

beta
Vitaliy Filippov 2018-03-22 20:43:02 +03:00
parent 65e825d471
commit a1e873904f
10 changed files with 127 additions and 30 deletions

View File

@ -106,8 +106,13 @@ sub DB_COLUMNS
# FIXME kill op_sys and rep_platform completely, make them custom fields
push @columns, 'op_sys' if Bugzilla->get_field('op_sys')->enabled;
push @columns, 'rep_platform' if Bugzilla->get_field('rep_platform')->enabled;
push @columns, map { $_->name }
grep { $_->type != FIELD_TYPE_MULTI_SELECT && $_->type != FIELD_TYPE_BUG_ID_REV }
push @columns,
map { $_->name }
grep {
$_->type != FIELD_TYPE_MULTI_SELECT &&
$_->type != FIELD_TYPE_EAV_TEXTAREA &&
$_->type != FIELD_TYPE_BUG_ID_REV
}
Bugzilla->active_custom_fields;
Bugzilla::Hook::process('bug_columns', { columns => \@columns });
@ -162,6 +167,7 @@ use constant CUSTOM_FIELD_VALIDATORS => {
FIELD_TYPE_BUG_ID_REV() => \&_set_bugid_rev_field,
FIELD_TYPE_BUG_URLS() => \&_set_default_field,
FIELD_TYPE_NUMERIC() => \&_set_numeric_field,
FIELD_TYPE_EAV_TEXTAREA() => \&_set_default_field,
};
sub SETTERS
@ -576,6 +582,9 @@ sub update
# Insert the values into the multiselect value tables
$self->save_multiselects($changes);
# Insert the values into satellite value tables
$self->save_eavs($changes);
# Save reversed bug_id fields
$self->save_reverse_bugid_fields($changes);
@ -932,6 +941,7 @@ sub check_dependent_fields
}
# Check other fields for empty values
elsif (!$self->{$fn} || ($field_obj->type == FIELD_TYPE_FREETEXT ||
$field_obj->type == FIELD_TYPE_EAV_TEXTAREA ||
$field_obj->type == FIELD_TYPE_TEXTAREA) && $self->{$fn} =~ /^\s*$/so)
{
my $nullable = $field_obj->check_is_nullable($self);
@ -945,6 +955,7 @@ sub check_dependent_fields
}
}
if (!$nullable && (!$self->{$fn} || ($field_obj->type == FIELD_TYPE_FREETEXT ||
$field_obj->type == FIELD_TYPE_EAV_TEXTAREA ||
$field_obj->type == FIELD_TYPE_TEXTAREA) && $self->{$fn} =~ /^\s*$/so))
{
ThrowUserError('field_not_nullable', { field => $field_obj });
@ -1457,6 +1468,31 @@ sub save_multiselects
}
}
sub save_eavs
{
my ($self, $changes) = @_;
my @eavs = Bugzilla->get_fields({ obsolete => 0, type => FIELD_TYPE_EAV_TEXTAREA });
foreach my $field (@eavs)
{
my $name = $field->name;
if (defined $self->{$name})
{
my $old = $self->{_old_self} && $self->{_old_self}->$name || '';
my $v = $self->{$name};
if ($v ne $old)
{
Bugzilla->dbh->do("DELETE FROM bug_$name WHERE bug_id=?", undef, $self->id);
if ($v ne '')
{
Bugzilla->dbh->do("INSERT INTO bug_$name (bug_id, value) VALUES (?, ?)", undef, $self->id, $v);
}
$changes->{$name} = [ $old, $v ];
}
}
}
}
sub save_see_also
{
my ($self, $changes) = @_;
@ -3652,7 +3688,9 @@ sub GetBugActivity
{
my $change = $operations[$i]{changes}[$j];
my $field = Bugzilla->get_field($change->{fieldname});
if ($change->{fieldname} eq 'longdesc' || $field->{type} eq FIELD_TYPE_TEXTAREA)
if ($change->{fieldname} eq 'longdesc' ||
$field->{type} == FIELD_TYPE_TEXTAREA ||
$field->{type} == FIELD_TYPE_EAV_TEXTAREA)
{
my $diff = Bugzilla::Diff->new($change->{removed}, $change->{added})->get_table;
if (!@$diff)
@ -4312,7 +4350,14 @@ sub get_value
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
"SELECT bug_id FROM bugs WHERE ".$field->value_field->name." = ?", undef, $self->id
);
return $self->{$attr};
}
elsif ($field->type == FIELD_TYPE_EAV_TEXTAREA)
{
($self->{$attr}) = Bugzilla->dbh->selectrow_array(
"SELECT value FROM bug_$attr WHERE bug_id=?", undef, $self->id
);
return $self->{$attr};
}
@ -4338,7 +4383,7 @@ sub fields
map { $_->name } Bugzilla->get_fields({
obsolete => 0,
custom => 1,
type => [ FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_BUG_ID_REV ],
type => [ FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_EAV_TEXTAREA, FIELD_TYPE_BUG_ID_REV ],
}),
);
Bugzilla::Hook::process('bug_fields', { fields => \@fields });
@ -4363,7 +4408,7 @@ sub _validate_attribute
# every DB column may be returned via an autoloaded accessor
(map { $_ => 1 } Bugzilla::Bug->DB_COLUMNS),
# multiselect, bug_id_rev fields
(map { $_->name => 1 } Bugzilla->get_fields({ type => [ FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_BUG_ID_REV ] })),
(map { $_->name => 1 } Bugzilla->get_fields({ type => [ FIELD_TYPE_MULTI_SELECT, FIELD_TYPE_EAV_TEXTAREA, FIELD_TYPE_BUG_ID_REV ] })),
# get_object accessors
(map { $_->name.'_obj' => 1 } Bugzilla->get_fields({ type => [ FIELD_TYPE_SINGLE_SELECT, FIELD_TYPE_MULTI_SELECT ] })),
};

View File

@ -129,6 +129,8 @@ use Cwd qw(abs_path);
FIELD_TYPE_NUMERIC
FIELD_TYPE_EXTURL
FIELD_TYPE_BUG_ID_REV
FIELD_TYPE_EAV_TEXTAREA
FIELD_TYPE__MAX
FLAG_VISIBLE
FLAG_NULLABLE
@ -392,6 +394,8 @@ 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 FIELD_TYPE_EAV_TEXTAREA => 33;
use constant FIELD_TYPE__MAX => 33;
use constant FLAG_VISIBLE => 0;
use constant FLAG_NULLABLE => -1;

View File

@ -816,12 +816,18 @@ sub _bz_add_field_table {
$self->bz_add_table($name);
}
sub bz_add_field_tables {
sub bz_add_field_tables
{
my ($self, $field) = @_;
$self->_bz_add_field_table($field->name,
$self->_bz_schema->FIELD_TABLE_SCHEMA, $field->type);
if ($field->type == FIELD_TYPE_MULTI_SELECT) {
if ($field->type == FIELD_TYPE_MULTI_SELECT ||
$field->type == FIELD_TYPE_SINGLE_SELECT)
{
$self->_bz_add_field_table(
$field->name, $self->_bz_schema->FIELD_TABLE_SCHEMA, $field->type
);
}
if ($field->type == FIELD_TYPE_MULTI_SELECT)
{
my $ms_table = "bug_" . $field->name;
$self->_bz_add_field_table($ms_table,
$self->_bz_schema->MULTI_SELECT_VALUE_TABLE);
@ -832,14 +838,27 @@ sub bz_add_field_tables {
$self->bz_add_fk($ms_table, 'value_id', {TABLE => $field->name,
COLUMN => 'id'});
}
elsif ($field->type == FIELD_TYPE_EAV_TEXTAREA)
{
my $ms_table = "bug_" . $field->name;
$self->_bz_add_field_table($ms_table, $self->_bz_schema->EAV_TEXTAREA_VALUE_TABLE);
$self->bz_add_fk($ms_table, 'bug_id', {TABLE => 'bugs', COLUMN => 'bug_id', DELETE => 'CASCADE'});
}
}
sub bz_drop_field_tables {
sub bz_drop_field_tables
{
my ($self, $field) = @_;
if ($field->type == FIELD_TYPE_MULTI_SELECT) {
if ($field->type == FIELD_TYPE_MULTI_SELECT ||
$field->type == FIELD_TYPE_EAV_TEXTAREA)
{
$self->bz_drop_table('bug_' . $field->name);
}
$self->bz_drop_table($field->name);
if ($field->type == FIELD_TYPE_MULTI_SELECT ||
$field->type == FIELD_TYPE_SINGLE_SELECT)
{
$self->bz_drop_table($field->name);
}
}
sub bz_drop_column

View File

@ -1326,6 +1326,15 @@ use constant MULTI_SELECT_VALUE_TABLE => {
bug_id_idx => {FIELDS => [qw(bug_id value_id)], TYPE => 'UNIQUE'},
],
};
use constant EAV_TEXTAREA_VALUE_TABLE => {
FIELDS => [
bug_id => {TYPE => 'INT4', NOTNULL => 1},
value => {TYPE => 'MEDIUMTEXT', NOTNULL => 1, DEFAULT => "''"},
],
INDEXES => [
bug_id_idx => {FIELDS => [qw(bug_id)], TYPE => 'UNIQUE'},
],
};
#--------------------------------------------------------------------------

View File

@ -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_BUG_ID_REV)
$type > FIELD_TYPE__MAX)
{
ThrowCodeError('invalid_customfield_type', { type => $saved_type });
}
@ -893,11 +893,8 @@ sub remove_from_db
$dbh->bz_drop_column('bugs', $name);
}
if ($self->is_select)
{
# Delete the table that holds the legal values for this field.
$dbh->bz_drop_field_tables($self);
}
# Delete the table that holds the legal values for this field.
$dbh->bz_drop_field_tables($self);
$self->set_visibility_values(undef);
$self->set_null_visibility_values(undef);
@ -1278,13 +1275,8 @@ sub create
# Create the database column that stores the data for this field.
$dbh->bz_add_column('bugs', $name, SQL_DEFINITIONS->{$type});
}
if ($obj->is_select)
{
# Create the table that holds the legal values for this field.
$dbh->bz_add_field_tables($obj);
}
# Create the table that holds the legal values for this field.
$dbh->bz_add_field_tables($obj);
# Add foreign keys
if ($type == FIELD_TYPE_SINGLE_SELECT)
{

View File

@ -77,6 +77,7 @@ $Bugzilla::messages->{en} = {
FIELD_TYPE_NUMERIC() => 'Numeric',
FIELD_TYPE_EXTURL() => 'External URL',
FIELD_TYPE_BUG_ID_REV() => $terms->{Bug}.' ID reverse',
FIELD_TYPE_EAV_TEXTAREA() => 'Large Text Box (separate table)',
},
control_options => {
CONTROLMAPNA() => 'NA',

View File

@ -616,6 +616,12 @@ sub STATIC_COLUMNS
" FROM ".$type->REL_TABLE.", $t WHERE $t.".$type->ID_FIELD."=".$type->REL_TABLE.".value_id".
" AND ".$type->REL_TABLE.".bug_id=bugs.bug_id)";
}
elsif ($field->type == FIELD_TYPE_EAV_TEXTAREA)
{
my $t = "bug_".$field->name;
$columns->{$id}->{name} = "$t.value";
$columns->{$id}->{joins} = [ "LEFT JOIN $t ON $t.bug_id=bugs.bug_id" ];
}
elsif ($bug_columns->{$id})
{
$columns->{$id}->{name} ||= "bugs.$id";
@ -701,6 +707,17 @@ sub STATIC_COLUMNS
sortkey => 1,
};
}
elsif ($subfield->type == FIELD_TYPE_MULTI_SELECT)
{
my $t = 'bug_'.$subfield->name;
$columns->{$id.'_'.$subid} = {
name => "bugs_$id"."_$t.value",
title => $field->description . ' ' . $subfield->description,
joins => [ @$join, "LEFT JOIN $t bugs_$id"."_$t ON bugs_$id"."_$t.bug_id=bugs_$id.bug_id" ],
subid => $subid,
sortkey => 1,
};
}
}
}

View File

@ -126,7 +126,7 @@
<option value="[% v.id %]"[% ' selected="selected"' IF cur_default.${v.id} %]>[% v.name | html %]</option>
[% END %]
</select>
[% ELSIF f.type == constants.FIELD_TYPE_TEXTAREA %]
[% ELSIF f.type == constants.FIELD_TYPE_TEXTAREA || f.type == constants.FIELD_TYPE_EAV_TEXTAREA %]
<textarea cols="50" rows="5" name="default_[% f.name | html %]" id="default_[% f.name | html %]">[% f.get_default_value(this_value.id) | html %]</textarea>
[% ELSE %]
<input type="text" name="default_[% f.name | html %]" id="default_[% f.name | html %]" value="[% f.get_default_value(this_value.id) | html %]" />

View File

@ -226,7 +226,7 @@ var close_status_array = [
[% END %]
[% INCLUDE custom_fields style = "width: 40em"
cf = Bugzilla.active_custom_fields({ 'type' => constants.FIELD_TYPE_TEXTAREA }) %]
cf = Bugzilla.active_custom_fields({ 'type' => [ constants.FIELD_TYPE_TEXTAREA, constants.FIELD_TYPE_EAV_TEXTAREA ] }) %]
[% INCLUDE custom_fields style = "min-width: 20em; max-width: 40em"
cf = Bugzilla.active_custom_fields({ 'type' => constants.FIELD_TYPE_MULTI_SELECT }) %]

View File

@ -55,6 +55,7 @@
bug.id && field.type != constants.FIELD_TYPE_BUG_ID_REV &&
field.type != constants.FIELD_TYPE_MULTI_SELECT &&
field.type != constants.FIELD_TYPE_TEXTAREA &&
field.type != constants.FIELD_TYPE_EAV_TEXTAREA &&
field.type != constants.FIELD_TYPE_BUG_URLS &&
field.type != constants.FIELD_TYPE_BUG_ID %]
@ -259,6 +260,15 @@
cols = 30
defaultcontent = value
tabindex = tabindex %]
[% CASE constants.FIELD_TYPE_EAV_TEXTAREA %]
[% INCLUDE global/textarea.html.tmpl
id = field.name
name = field.name
minrows = 4
maxrows = 8
cols = 30
defaultcontent = value
tabindex = tabindex %]
[% CASE constants.FIELD_TYPE_BUG_URLS %]
[% '<ul class="bug_urls">' IF value.size %]
[% FOREACH url = value %]
@ -292,7 +302,7 @@
[% IF show_search_link %]
</td><td style="padding-left: 5px">[% PROCESS search_link %](search)</a></td></tr></table>
[% END %]
[% ELSIF field.type == constants.FIELD_TYPE_TEXTAREA %]
[% ELSIF field.type == constants.FIELD_TYPE_TEXTAREA || field.type == constants.FIELD_TYPE_EAV_TEXTAREA %]
<div class="uneditable_textarea">[% value | html | wrap_comment %]</div>
[% ELSIF field.type == constants.FIELD_TYPE_BUG_ID %]
[% IF bug.${field.name} %]