Bug 45485, Bug 53617 - Multiple visibility values for fields and values. Рефакнутые, с убранным безумием на 500 строк.

git-svn-id: svn://svn.office.custis.ru/3rdparty/bugzilla.org/trunk@681 6955db30-a419-402b-8a0d-67ecbb4d7f56
master
vfilippov 2010-03-12 19:18:39 +00:00
parent 8681814366
commit 44729bd176
23 changed files with 423 additions and 544 deletions

View File

@ -212,9 +212,10 @@ sub update_params {
# --- REMOVE OLD PARAMS ---
my %oldparams;
my %actual = map { $_->{name} => 1 } @param_list;
# Remove any old params
foreach my $item (keys %$param) {
if (!grep($_ eq $item, map ($_->{'name'}, @param_list))) {
if (!$actual{$item}) {
$oldparams{$item} = $param->{$item};
delete $param->{$item};
}

View File

@ -218,6 +218,8 @@ use constant FIELD_TABLE_SCHEMA => {
sortkey => {TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0},
isactive => {TYPE => 'BOOLEAN', NOTNULL => 1,
DEFAULT => 'TRUE'},
# CustIS Bug 53617 - visibility_value_id is removed from here
# (migrated to fieldvaluecontrol table)
],
# Note that bz_add_field_table should prepend the table name
# to these index names.
@ -664,10 +666,11 @@ use constant ABSTRACT_SCHEMA => {
DEFAULT => 'FALSE'},
buglist => {TYPE => 'BOOLEAN', NOTNULL => 1,
DEFAULT => 'FALSE'},
visibility_field_id => {TYPE => 'INT3',
visibility_field_id => {TYPE => 'INT3',
REFERENCES => {TABLE => 'fielddefs',
COLUMN => 'id'}},
visibility_value_id => {TYPE => 'INT2'},
# CustIS Bug 53617 - visibility_value_id is removed from here
# (migrated to fieldvaluecontrol table)
value_field_id => {TYPE => 'INT3',
REFERENCES => {TABLE => 'fielddefs',
COLUMN => 'id'}},
@ -730,7 +733,6 @@ use constant ABSTRACT_SCHEMA => {
bug_status_value_idx => {FIELDS => ['value'],
TYPE => 'UNIQUE'},
bug_status_sortkey_idx => ['sortkey', 'value'],
bug_status_visibility_value_id_idx => ['visibility_value_id'],
],
},
@ -740,7 +742,6 @@ use constant ABSTRACT_SCHEMA => {
resolution_value_idx => {FIELDS => ['value'],
TYPE => 'UNIQUE'},
resolution_sortkey_idx => ['sortkey', 'value'],
resolution_visibility_value_id_idx => ['visibility_value_id'],
],
},
@ -750,7 +751,6 @@ use constant ABSTRACT_SCHEMA => {
bug_severity_value_idx => {FIELDS => ['value'],
TYPE => 'UNIQUE'},
bug_severity_sortkey_idx => ['sortkey', 'value'],
bug_severity_visibility_value_id_idx => ['visibility_value_id'],
],
},
@ -760,7 +760,6 @@ use constant ABSTRACT_SCHEMA => {
priority_value_idx => {FIELDS => ['value'],
TYPE => 'UNIQUE'},
priority_sortkey_idx => ['sortkey', 'value'],
priority_visibility_value_id_idx => ['visibility_value_id'],
],
},
@ -770,7 +769,6 @@ use constant ABSTRACT_SCHEMA => {
rep_platform_value_idx => {FIELDS => ['value'],
TYPE => 'UNIQUE'},
rep_platform_sortkey_idx => ['sortkey', 'value'],
rep_platform_visibility_value_id_idx => ['visibility_value_id'],
],
},
@ -780,7 +778,6 @@ use constant ABSTRACT_SCHEMA => {
op_sys_value_idx => {FIELDS => ['value'],
TYPE => 'UNIQUE'},
op_sys_sortkey_idx => ['sortkey', 'value'],
op_sys_visibility_value_id_idx => ['visibility_value_id'],
],
},

View File

@ -71,13 +71,15 @@ package Bugzilla::Field;
use strict;
use base qw(Exporter Bugzilla::Object);
@Bugzilla::Field::EXPORT = qw(check_field get_field_id get_legal_field_values);
@Bugzilla::Field::EXPORT = qw(check_field get_field_id get_legal_field_values update_visibility_values);
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Util;
use Scalar::Util qw(blessed);
use Encode;
use JSON;
###############################
#### Initialization ####
@ -98,7 +100,6 @@ use constant DB_COLUMNS => qw(
enter_bug
buglist
visibility_field_id
visibility_value_id
value_field_id
);
@ -118,7 +119,6 @@ use constant VALIDATORS => {
use constant UPDATE_VALIDATORS => {
value_field_id => \&_check_value_field_id,
visibility_value_id => \&_check_control_value,
};
use constant UPDATE_COLUMNS => qw(
@ -129,7 +129,6 @@ use constant UPDATE_COLUMNS => qw(
enter_bug
buglist
visibility_field_id
visibility_value_id
value_field_id
type
@ -340,22 +339,6 @@ sub _check_visibility_field_id {
return $field->id;
}
sub _check_control_value {
my ($invocant, $value_id, $field_id) = @_;
my $field;
if (blessed $invocant) {
$field = $invocant->visibility_field;
}
elsif ($field_id) {
$field = $invocant->new($field_id);
}
# When no field is set, no value is set.
return undef if !$field;
my $value_obj = Bugzilla::Field::Choice->type($field)
->check({ id => $value_id });
return $value_obj->id;
}
=pod
=head2 Instance Properties
@ -486,9 +469,9 @@ objects.
=cut
sub is_select {
return ($_[0]->type == FIELD_TYPE_SINGLE_SELECT
|| $_[0]->type == FIELD_TYPE_MULTI_SELECT) ? 1 : 0
sub is_select {
return ($_[0]->type == FIELD_TYPE_SINGLE_SELECT
|| $_[0]->type == FIELD_TYPE_MULTI_SELECT) ? 1 : 0
}
sub legal_values {
@ -505,9 +488,9 @@ sub legal_values {
sub restricted_legal_values
{
my $self = shift;
my ($value) = @_;
return $self->legal_values unless $value;
return $value->controlled_plus_generic->{$self->name};
my ($controller_value) = @_;
return $self->legal_values unless $controller_value;
return $controller_value->controlled_plus_generic->{$self->name};
}
=pod
@ -528,36 +511,50 @@ Returns undef if there is no field that controls this field's visibility.
sub visibility_field {
my $self = shift;
if ($self->{visibility_field_id}) {
$self->{visibility_field} ||=
$self->{visibility_field} ||=
$self->new($self->{visibility_field_id});
}
return $self->{visibility_field};
}
=pod
=over
=item C<visibility_value>
If we have a L</visibility_field>, then what value does that field have to
be set to in order to show this field? Returns a L<Bugzilla::Field::Choice>
or undef if there is no C<visibility_field> set.
=back
=cut
sub visibility_value {
sub visibility_values
{
my $self = shift;
if ($self->{visibility_field_id}) {
require Bugzilla::Field::Choice;
$self->{visibility_value} ||=
Bugzilla::Field::Choice->type($self->visibility_field)->new(
$self->{visibility_value_id});
my $f;
if ($self->visibility_field && !($f = $self->{visibility_values}))
{
$f = Bugzilla->dbh->selectcol_arrayref(
"SELECT visibility_value_id FROM fieldvaluecontrol WHERE field_id=? AND value_id=0",
undef, $self->id);
if (@$f)
{
my $type = Bugzilla::Field::Choice->type($self->visibility_field);
$f = $type->match({ id => $f });
}
$self->{visibility_values} = $f;
}
return $self->{visibility_value};
return $f;
}
sub has_visibility_value
{
my $self = shift;
my ($value) = @_;
ref $value and $value = $value->id;
my %f = map { $_->id => 1 } @{$self->visibility_values};
return $f{$value};
}
# Check visibility of field for a bug
sub check_visibility
{
my $self = shift;
my ($bug) = @_;
my $field = $self->visibility_field;
$bug && $field or return 1;
$field = $bug->{$field->name};
my %f = map { $_->name => 1 } @{$self->visibility_values};
return $f{$field};
}
=pod
@ -575,7 +572,7 @@ field controls the visibility of.
sub controls_visibility_of {
my $self = shift;
$self->{controls_visibility_of} ||=
$self->{controls_visibility_of} ||=
Bugzilla::Field->match({ visibility_field_id => $self->id });
return $self->{controls_visibility_of};
}
@ -648,8 +645,6 @@ They will throw an error if you try to set the values to something invalid.
=item C<set_visibility_field>
=item C<set_visibility_value>
=item C<set_value_field>
=back
@ -662,18 +657,26 @@ sub set_obsolete { $_[0]->set('obsolete', $_[1]); }
sub set_sortkey { $_[0]->set('sortkey', $_[1]); }
sub set_in_new_bugmail { $_[0]->set('mailhead', $_[1]); }
sub set_buglist { $_[0]->set('buglist', $_[1]); }
sub set_visibility_field {
sub set_visibility_field
{
my ($self, $value) = @_;
$self->set('visibility_field_id', $value);
delete $self->{visibility_field};
delete $self->{visibility_value};
delete $self->{visibility_values};
}
sub set_visibility_value {
my ($self, $value) = @_;
$self->set('visibility_value_id', $value);
delete $self->{visibility_value};
sub set_visibility_values
{
my $self = shift;
my ($value_ids) = @_;
update_visibility_values($self->visibility_field, $self, 0, $self->visibility_values, $value_ids);
delete $self->{visibility_values};
return @$value_ids;
}
sub set_value_field {
sub set_value_field
{
my ($self, $value) = @_;
$self->set('value_field_id', $value);
delete $self->{value_field};
@ -760,7 +763,9 @@ sub remove_from_db {
$dbh->bz_drop_field_tables($self);
}
$dbh->bz_commit_transaction()
$self->set_visibility_values(undef);
$dbh->bz_commit_transaction();
}
=pod
@ -839,10 +844,6 @@ sub run_create_validators {
"SELECT MAX(sortkey) + 100 FROM fielddefs") || 100;
}
$params->{visibility_value_id} =
$class->_check_control_value($params->{visibility_value_id},
$params->{visibility_field_id});
my $type = $params->{type} || 0;
$params->{value_field_id} =
$class->_check_value_field_id($params->{value_field_id},
@ -851,17 +852,6 @@ sub run_create_validators {
return $params;
}
sub update {
my $self = shift;
my $changes = $self->SUPER::update(@_);
my $dbh = Bugzilla->dbh;
if ($changes->{value_field_id} && $self->is_select) {
$dbh->do("UPDATE " . $self->name . " SET visibility_value_id = NULL");
}
return $changes;
}
=pod
=over
@ -1089,6 +1079,66 @@ sub get_field_id {
return $id
}
# Shared between Bugzilla::Field and Bugzilla::Field::Choice
sub update_visibility_values
{
my ($controller_field, $controlled_field, $controlled_value, $old_ids, $value_ids) = @_;
Bugzilla->dbh->do(
"DELETE FROM fieldvaluecontrol WHERE field_id=? AND value_id=?",
undef, $controlled_field->id, $controlled_value);
defined($value_ids) or return undef;
ref $value_ids or $value_ids = [ $value_ids ];
my $type = Bugzilla::Field::Choice->type($controller_field);
@$value_ids = map { $_ ? $type->check({ id => $_ }) : () } @$value_ids;
my ($a, $r) = diff_arrays([map { $_->id } @$value_ids], [map { $_->id } @$old_ids]);
if (@$value_ids)
{
Bugzilla->dbh->do(
"INSERT INTO fieldvaluecontrol (field_id, value_id, visibility_value_id) VALUES ".
join(",", ("(?,?,?)") x @$value_ids),
undef, map { ($controlled_field->id, $controlled_value, $_->id) } @$value_ids);
}
}
# Moved from bug/field-events.js.tmpl
sub json_visibility
{
my $self = shift;
my $show = { fields => {}, values => {} };
foreach my $controlled (@{$self->controls_visibility_of})
{
$show->{fields}->{$controlled->name} = { map { $_->id => 1 } @{$controlled->visibility_values} };
}
$show->{legal} = [ map { [ $_->id, $_->name ] } @{$self->legal_values} ];
foreach my $value (@{$self->legal_values})
{
foreach my $controlled_field (keys %{$value->controlled_values})
{
foreach my $controlled_value (@{$value->controlled_values->{$controlled_field}})
{
$show->{values}->{$controlled_field}->{$controlled_value->id}->{$value->id} = 1;
}
}
}
$show = encode_json($show);
Encode::_utf8_on($show);
return $show;
}
1;
__END__
[% FOREACH controlled_field = field.controls_visibility_of %]
[% FOREACH val = controlled_field.visibility_values %]
showFieldWhen['[% field.name | js %]']['[% val.name | js %]']['[% controlled_field.name | js %]'] = true;
[% END %]
[% END %]
[% FOREACH legal_value = field.legal_values %]
[% FOREACH controlled_field = legal_value.controlled_plus_generic.keys %]
[% FOREACH val = legal_value.controlled_plus_generic.$controlled_field %]
showValueWhen['[% field.name | js %]'][[% val.id %]]['[% controlled_field | js %]'][[% legal_value.id %]] = true;
[% END %]
[% END %]
[% END %]

View File

@ -193,7 +193,7 @@ sub remove_from_db {
{ field => $self->field, value => $self });
}
$self->_check_if_controller();
$self->set_visibility_values([]);
$self->set_visibility_values(undef);
$self->SUPER::remove_from_db();
}
@ -202,7 +202,7 @@ sub _check_if_controller {
my $self = shift;
my $vis_fields = $self->controls_visibility_of_fields;
my $values = $self->controlled_values;
if (@$vis_fields || scalar(keys %$values)) {
if (@$vis_fields || scalar grep { @{$values->{$_}} } keys %$values) {
ThrowUserError('fieldvalue_is_controller',
{ value => $self, fields => [map($_->name, @$vis_fields)],
vals => $values });
@ -269,89 +269,101 @@ sub is_static {
return 0;
}
sub controls_visibility_of_fields {
sub controls_visibility_of_fields
{
my $self = shift;
$self->{controls_visibility_of_fields} ||= Bugzilla::Field->match(
{ visibility_field_id => $self->field->id,
visibility_value_id => $self->id });
return $self->{controls_visibility_of_fields};
my $f;
unless ($f = $self->{controls_visibility_of_fields})
{
$f = Bugzilla->dbh->selectcol_arrayref(
"SELECT f.id FROM fielddefs f, fieldvaluecontrol c WHERE c.field_id=f.id".
" AND f.visibility_field_id=? AND c.visibility_value_id=? AND c.value_id=0",
undef, $self->field->id, $self->id
);
$f = Bugzilla::Field->match({ id => $f });
$self->{controls_visibility_of_fields} = $f;
}
return $f;
}
sub controlled_values
{
my $self = shift;
return $self->{controlled_values} if defined $self->{controlled_values};
my $fields = $self->field->controls_values_of;
my %controlled_values;
# TODO move this into Bugzilla::Field::Choice::match() with MATCH_JOIN
# but no MATCH_JOIN by now is available
foreach my $field (@$fields) {
my $type = Bugzilla::Field::Choice->type($field);
my $sql =
"SELECT f.".join(", f.", $type->DB_COLUMNS).
" FROM fieldvaluecontrol c, ".$type->DB_TABLE." f".
" WHERE c.field_id=? AND c.visibility_value_id=? AND c.value_id=f.id".
" ORDER BY f.sortkey";
# Обходим самозарождение греха при конкатенации DB_COLUMNS и DB_TABLE
trick_taint($sql);
my $f = Bugzilla->dbh->selectall_arrayref($sql, {Slice=>{}}, $field->id, $self->id) || [];
$f = [ map { bless $_, $type } @$f ];
$controlled_values{$field->name} = $f;
my $controlled_values;
unless ($controlled_values = $self->{controlled_values})
{
$controlled_values = {};
my $fields = $self->field->controls_values_of;
foreach my $field (@$fields)
{
my $f = Bugzilla->dbh->selectcol_arrayref(
"SELECT value_id FROM fieldvaluecontrol WHERE field_id=? AND visibility_value_id=? AND value_id!=0",
undef, $field->id, $self->id);
if (@$f)
{
my $type = Bugzilla::Field::Choice->type($field);
$f = $type->match({ id => $f });
}
$controlled_values->{$field->name} = $f;
}
$self->{controlled_values} = $controlled_values;
}
$self->{controlled_values} = \%controlled_values;
return $self->{controlled_values};
return $controlled_values;
}
sub controlled_plus_generic
{
my $self = shift;
return $self->{controlled_plus_generic} if defined $self->{controlled_plus_generic};
my $fields = $self->field->controls_values_of;
my %controlled_values;
# TODO move this into Bugzilla::Field::Choice::match() with MATCH_JOIN
# but no MATCH_JOIN by now is available
foreach my $field (@$fields) {
my $type = Bugzilla::Field::Choice->type($field);
my $sql =
"(SELECT f.".join(", f.", $type->DB_COLUMNS).
" FROM fieldvaluecontrol c, ".$type->DB_TABLE." f".
" WHERE c.field_id=? AND c.visibility_value_id=? AND c.value_id=f.id)".
" UNION ALL (SELECT f.".join(", f.", $type->DB_COLUMNS).
" FROM ".$type->DB_TABLE." f LEFT JOIN fieldvaluecontrol c ON c.value_id=f.id AND c.field_id=?".
" WHERE c.field_id IS NULL)".
" ORDER BY sortkey";
# Обходим самозарождение греха при конкатенации DB_COLUMNS и DB_TABLE
trick_taint($sql);
my $f = Bugzilla->dbh->selectall_arrayref($sql, {Slice=>{}}, $field->id, $self->id, $field->id) || [];
$f = [ map { bless $_, $type } @$f ];
$controlled_values{$field->name} = $f;
my $controlled_values;
unless ($controlled_values = $self->{controlled_plus_generic})
{
my $fields = $self->field->controls_values_of;
foreach my $field (@$fields)
{
my $f = Bugzilla->dbh->selectcol_arrayref(
"SELECT value_id FROM fieldvaluecontrol WHERE field_id=? AND visibility_value_id=? AND value_id!=0
UNION ALL SELECT id FROM ".$field->name." f LEFT JOIN fieldvaluecontrol c ON c.value_id=f.id AND c.field_id=? WHERE c.visibility_value_id IS NULL",
undef, $field->id, $self->id, $field->id);
if (@$f)
{
my $type = Bugzilla::Field::Choice->type($field);
$f = $type->match({ id => $f });
}
$controlled_values->{$field->name} = $f;
}
$self->{controlled_plus_generic} = $controlled_values;
}
$self->{controlled_plus_generic} = \%controlled_values;
return $self->{controlled_plus_generic};
return $controlled_values;
}
sub visibility_values
{
my $self = shift;
my $f;
unless ($f = $self->{visibility_values})
if ($self->field->value_field && !($f = $self->{visibility_values}))
{
# TODO move this into Bugzilla::Field::Choice::match() with MATCH_JOIN
# but no MATCH_JOIN by now is available
my $type = Bugzilla::Field::Choice->type($self->field->value_field);
my $sql =
"SELECT f.".join(", f.", $type->DB_COLUMNS).
" FROM fieldvaluecontrol c, ".$type->DB_TABLE." f".
" WHERE c.field_id=? AND c.visibility_value_id=f.id AND c.value_id=?";
# Обходим самозарождение греха при конкатенации DB_COLUMNS и DB_TABLE
trick_taint($sql);
$f = Bugzilla->dbh->selectall_arrayref($sql, {Slice=>{}}, $self->field->id, $self->id) || [];
$f = [ map { bless $_, $type } @$f ];
$f = Bugzilla->dbh->selectcol_arrayref(
"SELECT visibility_value_id FROM fieldvaluecontrol WHERE field_id=? AND value_id=?",
undef, $self->field->id, $self->id);
if (@$f)
{
my $type = Bugzilla::Field::Choice->type($self->field->value_field);
$f = $type->match({ id => $f });
}
$self->{visibility_values} = $f;
}
return $f;
}
sub has_visibility_value
{
my $self = shift;
my ($value) = @_;
ref $value and $value = $value->id;
my %f = map { $_->id => 1 } @{$self->visibility_values};
return $f{$value};
}
############
# Mutators #
############
@ -363,21 +375,7 @@ sub set_visibility_values
{
my $self = shift;
my ($value_ids) = @_;
return undef if !ref $value_ids || $value_ids !~ 'ARRAY';
my $type = Bugzilla::Field::Choice->type($self->field->value_field);
@$value_ids = map { $_ ? $type->check({ id => $_ }) : () } @$value_ids;
my ($a, $r) = diff_arrays([map { $_->id } @$value_ids], [map { $_->id } @{$self->visibility_values}]);
return undef unless @$a || @$r;
Bugzilla->dbh->do(
"DELETE FROM fieldvaluecontrol WHERE field_id=? AND value_id=?",
undef, $self->field->id, $self->id);
if (@$value_ids)
{
Bugzilla->dbh->do(
"INSERT INTO fieldvaluecontrol (field_id, value_id, visibility_value_id) VALUES ".
join(",", ("(?,?,?)") x @$value_ids),
undef, map { ($self->field->id, $self->id, $_->id) } @$value_ids);
}
update_visibility_values($self->field->value_field, $self->field, $self->id, $self->visibility_values, $value_ids);
delete $self->{visibility_values};
return @$value_ids;
}

View File

@ -88,7 +88,7 @@ sub update_fielddefs_definition {
}
$dbh->bz_add_column('fielddefs', 'visibility_field_id', {TYPE => 'INT3'});
$dbh->bz_add_column('fielddefs', 'visibility_value_id', {TYPE => 'INT2'});
# visibility_value_id is not added anymore during update - it's now in fieldvaluecontrol
$dbh->bz_add_column('fielddefs', 'value_field_id', {TYPE => 'INT3'});
$dbh->bz_add_index('fielddefs', 'fielddefs_value_field_id_idx',
['value_field_id']);

View File

@ -55,6 +55,7 @@ use File::Find;
use File::Path qw(rmtree mkpath);
use File::Spec;
use IO::Dir;
use JSON;
use base qw(Template);
@ -530,6 +531,11 @@ sub create {
return $var;
},
json => sub {
my ($var) = @_;
return encode_json($var);
},
# Converts data to base64
base64 => sub {
my ($data) = @_;

View File

@ -56,7 +56,7 @@ elsif ($action eq 'add') {
elsif ($action eq 'new') {
check_token_data($token, 'add_field');
$vars->{'field'} = Bugzilla::Field->create({
my $field = $vars->{'field'} = Bugzilla::Field->create({
name => scalar $cgi->param('name'),
description => scalar $cgi->param('desc'),
type => scalar $cgi->param('type'),
@ -67,9 +67,9 @@ elsif ($action eq 'new') {
custom => 1,
buglist => (scalar $cgi->param('type') == FIELD_TYPE_MULTI_SELECT ? 0 : 1),
visibility_field_id => scalar $cgi->param('visibility_field_id'),
visibility_value_id => scalar $cgi->param('visibility_value_id'),
value_field_id => scalar $cgi->param('value_field_id'),
});
$field->set_visibility_values([ $cgi->param('visibility_value_id') ]);
delete_token($token);
@ -108,7 +108,7 @@ elsif ($action eq 'update') {
# At the moment, though, it has no effect for non-custom fields.
$field->set_enter_bug($cgi->param('enter_bug'));
$field->set_visibility_field($cgi->param('visibility_field_id'));
$field->set_visibility_value($cgi->param('visibility_value_id'));
$field->set_visibility_values([ $cgi->param('visibility_value_id') ]);
$field->set_value_field($cgi->param('value_field_id'));
}
$field->update();

View File

@ -105,26 +105,40 @@ if (!$dbh->bz_column_info('components', 'default_version'))
}
# Bug 53617 - Ограничение Custom Fields двумя и более значениями контролирующего поля
my @standard_fields =
qw(bug_status resolution priority bug_severity op_sys rep_platform);
my $custom_fields = $dbh->selectcol_arrayref(
'SELECT name FROM fielddefs WHERE custom = 1 AND type IN (?,?)',
undef, FIELD_TYPE_SINGLE_SELECT, FIELD_TYPE_MULTI_SELECT);
foreach my $field (@standard_fields, @$custom_fields)
my @standard_fields = qw(bug_status resolution priority bug_severity op_sys rep_platform);
my $custom_fields = $dbh->selectall_arrayref(
'SELECT * FROM fielddefs WHERE (custom=1 AND type IN (?,?)) OR name IN ('.
join(',',('?') x @standard_fields).')', {Slice=>{}},
FIELD_TYPE_SINGLE_SELECT, FIELD_TYPE_MULTI_SELECT, @standard_fields);
foreach my $field (@$custom_fields)
{
next unless $dbh->bz_table_info($field);
if ($dbh->bz_column_info($field, 'visibility_value_id'))
if ($dbh->bz_table_info($field->{name}) &&
$dbh->bz_column_info($field->{name}, 'visibility_value_id'))
{
print "Migrating $field visibility_value_id into fieldvaluecontrol\n";
print "Migrating $field->{name}'s visibility_value_id into fieldvaluecontrol\n";
$dbh->do(
"REPLACE INTO fieldvaluecontrol (field_id, visibility_value_id, value_id)".
" SELECT f.id, v.visibility_value_id, v.id FROM fielddefs f, $field v".
" WHERE f.name=? AND v.visibility_value_id IS NOT NULL", undef, $field);
# Пока не удаляем никаких колонок
#$dbh->bz_drop_column($field, 'visibility_value_id');
" SELECT f.id, v.visibility_value_id, v.id FROM fielddefs f, `$field->{name}` v".
" WHERE f.name=? AND v.visibility_value_id IS NOT NULL", undef, $field->{name});
print "Making backup of table $field->{name}\n";
$dbh->do("CREATE TABLE `backup_$field->{name}_".time."` AS SELECT * FROM `$field->{name}`");
print "Dropping column $field->{name}.visibility_value_id\n";
#$dbh->bz_drop_column($field->{name}, 'visibility_value_id');
}
}
if ($dbh->bz_column_info('fielddefs', 'visibility_value_id'))
{
print "Migrating fielddefs's visibility_value_id into fieldvaluecontrol\n";
$dbh->do(
"REPLACE INTO fieldvaluecontrol (field_id, visibility_value_id, value_id)".
" SELECT id, visibility_value_id, 0 FROM fielddefs WHERE visibility_value_id IS NOT NULL");
print "Making backup of table fielddefs\n";
$dbh->do("CREATE TABLE `backup_fielddefs_".time."` AS SELECT * FROM fielddefs");
print "Dropping column fielddefs.visibility_value_id\n";
#$dbh->bz_drop_column('fielddefs', 'visibility_value_id');
}
# Testopia:
if ($dbh->bz_table_info('test_fielddefs'))
{

View File

@ -164,29 +164,30 @@ sub fetch_wiki_category_xml
$_[0] = $wiki_url;
my $uri = URI->new($wiki_url . '?title=Special:Export&action=submit')->canonical;
# Дёргаем Special:Export и вытаскиваем список страниц категории
utf8::decode($category);
utf8::encode($category);
my $response = $ua->request(POST "$uri", [ addcat => 'Add', catname => $category, closure => 1 ]);
my $r = POST "$uri", Content => "addcat=Add&catname=".url_quote($category)."&closure=1";
my $response = $ua->request($r);
if (!$response->is_success)
{
# TODO показать ошибку
die "Could not POST $uri addcat=Добавить&catname=$category: ".$response->status_line;
die "Could not POST $uri addcat=Add&catname=$category: ".$response->status_line;
}
my $text = $response->content;
($text) = $text =~ m!<textarea[^<>]*>(.*?)</textarea>!iso;
decode_entities($text);
utf8::decode($text);
utf8::encode($text);
decode_entities($text);
# Дёргаем Special:Export и вытаскиваем саму XML-ку с последними ревизиями
$response = $ua->request(POST $uri, [
wpDownload => 1,
curonly => 1,
pages => $text,
]);
$response = $ua->request(POST $uri, Content => "wpDownload=1&curonly=1&pages=".url_quote($text));
if (!$response->is_success)
{
# TODO показать ошибку
die "Could not retrieve export XML file: ".$response->status_line;
}
return $response->content;
my $xml = $response->content;
if ($xml !~ /<\?\s*xml/so)
{
my ($line) = $xml =~ /^\s*([^\n]*)/so;
# TODO показать ошибку
die "Could not retrieve export XML file, got $line instead";
}
return $xml;
}

View File

@ -0,0 +1,5 @@
#!/usr/bin/perl
use strict;
Bugzilla->hook_args->{panel_modules}->{Testopia} = 'extensions::testopia::lib::Testopia::Config';

View File

@ -21,6 +21,99 @@
/* This library assumes that the needed YUI libraries have been loaded
already. */
var show_fields = {};
YAHOO.util.Event.addListener(window, 'load', initControlledFields);
function initControlledFields()
{
for (var i in show_fields)
initControlledField(i);
}
function initControlledField(i)
{
var f = document.getElementById(i);
YAHOO.util.Event.addListener(f, 'change', handleControllerField, f);
}
function getSelectedIds(sel)
{
var lm = sel.id.length+2;
var opt = {};
for (var i = 0; i < sel.options.length; i++)
{
if (sel.options[i].selected)
{
id = sel.options[i].id;
opt[id.substr(1, id.length-lm)] = true;
}
}
return opt;
}
function handleControllerField(e, controller)
{
var vis, label_container, field_container, id;
var opt = getSelectedIds(controller);
for (var controlled_id in show_fields[controller.id]['fields'])
{
vis = false;
for (var value in show_fields[controller.id]['fields'][controlled_id])
{
if (opt[value])
{
vis = true;
break;
}
}
label_container = document.getElementById('field_label_' + controlled_id);
field_container = document.getElementById('field_container_' + controlled_id);
if (vis)
{
YAHOO.util.Dom.removeClass(label_container, 'bz_hidden_field');
YAHOO.util.Dom.removeClass(field_container, 'bz_hidden_field');
}
else
{
YAHOO.util.Dom.addClass(label_container, 'bz_hidden_field');
YAHOO.util.Dom.addClass(field_container, 'bz_hidden_field');
}
}
var item, controlled, copt, controlled_value;
for (var controlled_id in show_fields[controller.id]['values'])
{
controlled = document.getElementById(controlled_id);
copt = getSelectedIds(controlled);
bz_clearOptions(controlled);
for (var i in show_fields[controlled.id]['legal'])
{
controlled_value = show_fields[controlled.id]['legal'][i];
vis = false;
item = show_fields[controller.id]['values'][controlled_id][controlled_value[0]];
if (!item)
vis = true;
else
{
for (var value in item)
{
if (opt[value])
{
vis = true;
break;
}
}
}
if (vis)
{
item = bz_createOptionInSelect(controlled, controlled_value[1], controlled_value[1]);
item.id = 'v'+controlled_value[0]+'_'+controlled_id;
if (copt[controlled_value[0]])
item.selected = true;
}
}
}
}
function createCalendar(name) {
var cal = new YAHOO.widget.Calendar('calendar_' + name,
'con_calendar_' + name);
@ -373,190 +466,8 @@ function updateCommentTagControl(checkbox, form) {
}
}
/**
* Says that a field should only be displayed when another field has
* a certain value. May only be called after the controller has already
* been added to the DOM.
*/
function showFieldWhen(controlled_id, controller_id, value) {
var controller = document.getElementById(controller_id);
// Note that we don't get an object for "controlled" here, because it
// might not yet exist in the DOM. We just pass along its id.
YAHOO.util.Event.addListener(controller, 'change',
handleVisControllerValueChange, [controlled_id, controller, value]);
}
/**
* Called by showFieldWhen when a field's visibility controller
* changes values.
*/
function handleVisControllerValueChange(e, args) {
var controlled_id = args[0];
var controller = args[1];
var value = args[2];
var label_container =
document.getElementById('field_label_' + controlled_id);
var field_container =
document.getElementById('field_container_' + controlled_id);
if (bz_valueSelected(controller, value)) {
YAHOO.util.Dom.removeClass(label_container, 'bz_hidden_field');
YAHOO.util.Dom.removeClass(field_container, 'bz_hidden_field');
}
else {
YAHOO.util.Dom.addClass(label_container, 'bz_hidden_field');
YAHOO.util.Dom.addClass(field_container, 'bz_hidden_field');
}
}
function showValueWhen(controlled_field_id, controlled_value_ids,
controller_field_id, controller_value_id)
{
var controller_field = document.getElementById(controller_field_id);
// Note that we don't get an object for the controlled field here,
// because it might not yet exist in the DOM. We just pass along its id.
YAHOO.util.Event.addListener(controller_field, 'change',
handleValControllerChange, [controlled_field_id, controlled_value_ids,
controller_field, controller_value_id]);
}
function handleValControllerChange(e, args) {
var controlled_field = document.getElementById(args[0]);
var controlled_value_ids = args[1];
var controller_field = args[2];
var controller_value_id = args[3];
var controller_item = document.getElementById(
_value_id(controller_field.id, controller_value_id));
for (var i = 0; i < controlled_value_ids.length; i++) {
var item = getPossiblyHiddenOption(controlled_field,
controlled_value_ids[i]);
if (item.disabled && controller_item && controller_item.selected) {
item = showOptionInIE(item, controlled_field);
YAHOO.util.Dom.removeClass(item, 'bz_hidden_option');
item.disabled = false;
}
else if (!item.disabled) {
YAHOO.util.Dom.addClass(item, 'bz_hidden_option');
if (item.selected) {
item.selected = false;
bz_fireEvent(controlled_field, 'change');
}
item.disabled = true;
hideOptionInIE(item, controlled_field);
}
}
}
// A convenience function to generate the "id" tag of an <option>
// based on the numeric id that Bugzilla uses for that value.
function _value_id(field_name, id) {
return 'v' + id + '_' + field_name;
}
/*********************************/
/* Code for Hiding Options in IE */
/*********************************/
/* IE 7 and below (and some other browsers) don't respond to "display: none"
* on <option> tags. However, you *can* insert a Comment Node as a
* child of a <select> tag. So we just insert a Comment where the <option>
* used to be. */
var ie_hidden_options = new Array();
function hideOptionInIE(anOption, aSelect) {
if (browserCanHideOptions(aSelect)) return;
var commentNode = document.createComment(anOption.value);
commentNode.id = anOption.id;
// This keeps the interface of Comments and Options the same for
// our other functions.
commentNode.disabled = true;
// replaceChild is very slow on IE in a <select> that has a lot of
// options, so we use replaceNode when we can.
if (anOption.replaceNode) {
anOption.replaceNode(commentNode);
}
else {
aSelect.replaceChild(commentNode, anOption);
}
// Store the comment node for quick access for getPossiblyHiddenOption
if (!ie_hidden_options[aSelect.id]) {
ie_hidden_options[aSelect.id] = new Array();
}
ie_hidden_options[aSelect.id][anOption.id] = commentNode;
}
function showOptionInIE(aNode, aSelect) {
if (browserCanHideOptions(aSelect)) return aNode;
// We do this crazy thing with innerHTML and createElement because
// this is the ONLY WAY that this works properly in IE.
var optionNode = document.createElement('option');
optionNode.innerHTML = aNode.data;
optionNode.value = aNode.data;
optionNode.id = aNode.id;
// replaceChild is very slow on IE in a <select> that has a lot of
// options, so we use replaceNode when we can.
if (aNode.replaceNode) {
aNode.replaceNode(optionNode);
}
else {
aSelect.replaceChild(optionNode, aNode);
}
delete ie_hidden_options[aSelect.id][optionNode.id];
return optionNode;
}
function initHidingOptionsForIE(select_name) {
var aSelect = document.getElementById(select_name);
if (browserCanHideOptions(aSelect)) return;
for (var i = 0; ;i++) {
var item = aSelect.options[i];
if (!item) break;
if (item.disabled) {
hideOptionInIE(item, aSelect);
i--; // Hiding an option means that the options array has changed.
}
}
}
function getPossiblyHiddenOption(aSelect, optionId) {
// Works always for <option> tags, and works for commentNodes
// in IE (but not in Webkit).
var id = _value_id(aSelect.id, optionId);
var val = document.getElementById(id);
// This is for WebKit and other browsers that can't "display: none"
// an <option> and also can't getElementById for a commentNode.
if (!val && ie_hidden_options[aSelect.id]) {
val = ie_hidden_options[aSelect.id][id];
}
return val;
}
var browser_can_hide_options;
function browserCanHideOptions(aSelect) {
/* As far as I can tell, browsers that don't hide <option> tags
* also never have a X position for <option> tags, even if
* they're visible. This is the only reliable way I found to
* differentiate browsers. So we create a visible option, see
* if it has a position, and then remove it. */
if (typeof(browser_can_hide_options) == "undefined") {
var new_opt = bz_createOptionInSelect(aSelect, '', '');
var opt_pos = YAHOO.util.Dom.getX(new_opt);
aSelect.removeChild(new_opt);
if (opt_pos) {
browser_can_hide_options = true;
}
else {
browser_can_hide_options = false;
}
}
return browser_can_hide_options;
}
/* (end) option hiding code */

View File

@ -26,11 +26,11 @@ function toggleCheckbox(this_checkbox, other_checkbox_id) {
var select_values = new Array();
[% USE Bugzilla %]
[% FOREACH sel_field = Bugzilla.get_fields({ is_select => 1 }) %]
select_values[[% sel_field.id FILTER js %]] = [
select_values[[% sel_field.id FILTER js %]] = [
[% FOREACH legal_value = sel_field.legal_values %]
[[% legal_value.id FILTER js %], '[% legal_value.name FILTER js %]'][% ',' UNLESS loop.last %]
[% END %]
];
];
[% END %]
function onChangeType(type_field) {

View File

@ -106,9 +106,15 @@
</option>
[% END %]
</select>
<label for="visibility_value_id"><strong>is set to:</strong></label>
<select name="visibility_value_id" id="visibility_value_id">
<option value=""></option>
<label for="visibility_value_id"><strong>&nbsp;is set to one of:</strong></label>
</td>
<td rowspan="2">
<select style="min-width: 100px" id="visibility_value_id" name="visibility_value_id" size="3" multiple="multiple" [% IF loop.first %]id="visibility_value_id"[% END %]>
[% FOREACH value = field.visibility_field.legal_values %]
<option value="[% value.id FILTER html %]"[% ' selected="selected"' IF field.has_visibility_value(value.id) %]>
[% value.name FILTER html %]
</option>
[% END %]
</select>
</td>
</tr>

View File

@ -98,14 +98,14 @@
</option>
[% END %]
</select>
<label for="visibility_value_id"><strong>is set to:</strong></label>
<select name="visibility_value_id" id="visibility_value_id">
<label for="visibility_value_id"><strong>&nbsp;is set to one of:</strong></label>
</td>
<td rowspan="2">
<select style="min-width: 100px" id="visibility_value_id" name="visibility_value_id" size="3" multiple="multiple" [% IF loop.first %]id="visibility_value_id"[% END %]>
[% FOREACH value = field.visibility_field.legal_values %]
<option value="[% value.id FILTER html %]"
[% ' selected="selected"'
IF field.visibility_value.id == value.id %]>
[% value.name FILTER html %]
</option>
<option value="[% value.id FILTER html %]"[% ' selected="selected"' IF field.has_visibility_value(value.id) %]>
[% value.name FILTER html %]
</option>
[% END %]
</select>
</td>

View File

@ -70,46 +70,22 @@
</label>
</th>
<td>
<input type="button" onclick="add_visibility_value()" value="Add an option" />
(Leave unset to have this value always appear.)
<a href="javascript:void(0)" onclick="document.getElementById('visibility_value_id').selectedIndex=-1">clear options</a> to make this value always appear
</td>
</tr>
<tr>
<td></td><td id="visibility_values_td">
<select name="visibility_value_id" id="visibility_value_id_0">
<td></td><td>
<select name="visibility_value_id" id="visibility_value_id" multiple="multiple" size="3">
<option></option>
[% FOREACH field_value = field.value_field.legal_values %]
[% NEXT IF field_value.name == '' %]
<option value="[% field_value.id FILTER none %]">
<option value="[% field_value.id FILTER none %]" [% ' selected="selected"' IF value.has_visibility_value(field_value.id) %]>
[%- field_value.name FILTER html -%]
</option>
[% END %]
</select>
</td>
</tr>
<script language="JavaScript">
<!--
function add_visibility_value()
{
var td = document.getElementById('visibility_values_td');
var sel = document.getElementById('visibility_value_id_0');
var o;
var n = document.createElement('span');
n.innerHTML = ' or <br>';
td.appendChild(n);
n = document.createElement('select');
n.name = "visibility_value_id";
for (var i = 0; i < sel.options.length; i++)
{
o = document.createElement('option');
o.value = sel.options[i].value;
o.text = sel.options[i].text;
n.options.add(o);
}
td.appendChild(n);
}
//-->
</script>
[% END %]
</table>
<input type="submit" id="create" value="Add">

View File

@ -64,55 +64,22 @@
Only appears when [%+ field.value_field.description FILTER html %] is set to:
</th>
<td>
<input type="button" onclick="add_visibility_value()" value="Add an option" />
(Leave unset to have this value always appear.)
<a href="javascript:void(0)" onclick="document.getElementById('visibility_value_id').selectedIndex=-1">clear options</a> to make this value always appear
</td>
</tr>
[% vis_values = value.visibility_values %]
[% SET vis_values = [{ id => -1 }] IF !vis_values OR vis_values.size <= 0 %]
[% SET vv_i = 0 %]
<tr>
<td></td><td id="visibility_values_td">
[% FOR vv = vis_values %]
[% " or <br>" IF vv_i %]
<select name="visibility_value_id" id="visibility_value_id_[% vv_i %]">
<td></td><td>
<select name="visibility_value_id" id="visibility_value_id" multiple="multiple" size="3">
<option></option>
[% FOREACH field_value = field.value_field.legal_values %]
[% NEXT IF field_value.name == '' %]
<option value="[% field_value.id FILTER none %]"
[% ' selected="selected"'
IF field_value.id == vv.id %]>
<option value="[% field_value.id FILTER none %]" [% ' selected="selected"' IF value.has_visibility_value(field_value.id) %]>
[%- field_value.name FILTER html -%]
</option>
[% END %]
</select>
[% SET vv_i = vv_i + 1 %]
[% END %]
</td>
</tr>
<script language="JavaScript">
<!--
function add_visibility_value()
{
var td = document.getElementById('visibility_values_td');
var sel = document.getElementById('visibility_value_id_0');
var o;
var n = document.createElement('span');
n.innerHTML = ' or <br>';
td.appendChild(n);
n = document.createElement('select');
n.name = "visibility_value_id";
for (var i = 0; i < sel.options.length; i++)
{
o = document.createElement('option');
o.value = sel.options[i].value;
o.text = sel.options[i].text;
n.options.add(o);
}
td.appendChild(n);
}
//-->
</script>
[% END %]
</table>

View File

@ -374,8 +374,8 @@ TUI_hide_default('expert_fields');
[% IF Param('useopsys') %]
<tr>
[% INCLUDE bug/field.html.tmpl
bug = default, field = select_fields.op_sys, editable = 1,
[% INCLUDE bug/field.html.tmpl
bug = default, field = select_fields.op_sys, editable = 1,
value = default.op_sys %]
</tr>
[% END %]
@ -392,7 +392,7 @@ TUI_hide_default('expert_fields');
[% IF Param('letsubmitterchoosepriority') %]
[% INCLUDE bug/field.html.tmpl
bug = default, field = select_fields.priority, editable = 1,
bug = default, field = select_fields.priority, editable = 1,
value = default.priority %]
[% ELSE %]
<td colspan="2">&nbsp;</td>
@ -799,12 +799,11 @@ TUI_hide_default('expert_fields');
</select>
[% IF sel.name == "bug_status" %]
<script type="text/javascript">
<!--
[%+ INCLUDE "bug/field-events.js.tmpl"
field = select_fields.bug_status %]
//-->
</script>
<script type="text/javascript">
<!--
show_fields['bug_status'] = [% select_fields.bug_status.json_visibility %];
//-->
</script>
[% END %]
</td>
[% END %]

View File

@ -459,7 +459,7 @@ document.changeform = document.[% cfname %];
[%#############%]
[%# PRODUCT #%]
[%#############%]
<tr>
[% IF bug.check_can_change_field('product', 0, 1) %]
[% prod_list = user.get_enterable_products %]
@ -470,11 +470,11 @@ document.changeform = document.[% cfname %];
[% INCLUDE bug/field.html.tmpl
bug = bug, field = select_fields.product,
override_legal_values = prod_list
override_legal_values = prod_list,
desc_url = 'describecomponents.cgi', value = bug.product
editable = bug.check_can_change_field('product', 0, 1) %]
</tr>
[%###############%]
[%###############%]
[%# Component #%]
[%###############%]
<tr>

View File

@ -1,40 +0,0 @@
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is the San Jose State
# University Foundation. Portions created by the Initial Developer
# are Copyright (C) 2008 the Initial Developer. All Rights Reserved.
#
# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
#%]
[%# INTERFACE:
# field: a Bugzilla::Field object
#%]
[% FOREACH controlled_field = field.controls_visibility_of %]
showFieldWhen('[% controlled_field.name FILTER js %]',
'[% field.name FILTER js %]',
'[% controlled_field.visibility_value.name FILTER js %]');
[% END %]
[% FOREACH legal_value = field.legal_values %]
[% FOREACH controlled_field = legal_value.controlled_values.keys %]
[% SET cont_ids = [] %]
[% FOREACH val = legal_value.controlled_values.$controlled_field %]
[% cont_ids.push(val.id) %]
[% END %]
showValueWhen('[% controlled_field FILTER js %]',
[[% cont_ids.join(',') FILTER js %]],
'[% field.name FILTER js %]',
[% legal_value.id FILTER js %]);
[% END %]
[% END %]

View File

@ -39,14 +39,7 @@
# with default field values being displayed on a page.
#%]
[% SET hidden = 0 %]
[% IF field.visibility_field.defined %]
[% IF !bug.${field.visibility_field.name}
.contains(field.visibility_value.name)
%]
[% SET hidden = 1 %]
[% END %]
[% END %]
[% SET hidden = !field.check_visibility(bug) %]
[% IF NOT no_tds %]
<th class="field_label [% ' bz_hidden_field' IF hidden %]"
@ -137,17 +130,15 @@
[% SET control_field = field.value_field.name %]
[% SET control_field = "product_obj" IF control_field == "product" %]
[% SET control_field = "component_obj" IF control_field == "component" %]
[% legal_values = field.restricted_legal_values(bug.${control_field}) %]
[% legal_values = field.restricted_legal_values(bug.$control_field) %]
[% END %]
[% FOREACH legal_value = legal_values %]
<option value="[% legal_value.name FILTER html %]"
id="v[% legal_value.id FILTER html %]_
[%- field.name FILTER html %]"
[%# We always show selected values, even if they should be
# hidden %]
id="v[% legal_value.id FILTER html %]_[% field.name FILTER html %]"
[% IF value.contains(legal_value.name).size %]
selected="selected"
[% END %]>
[% END %]
>
[%- legal_value.name FILTER html %]</option>
[% END %]
</select>
@ -164,8 +155,7 @@
<script type="text/javascript">
<!--
initHidingOptionsForIE('[% field.name FILTER js %]');
[%+ INCLUDE "bug/field-events.js.tmpl" field = field %]
show_fields['[% field.name | js %]'] = [% field.json_visibility %];
//-->
</script>

View File

@ -138,8 +138,8 @@
['[% "is_duplicate" IF bug.dup_id %]',
'[% bug.bug_status FILTER js %]'] );
[% INCLUDE "bug/field-events.js.tmpl" field = select_fields.bug_status %]
[% INCLUDE "bug/field-events.js.tmpl" field = select_fields.resolution %]
show_fields['bug_status'] = [% select_fields.bug_status.json_visibility %];
show_fields['resolution'] = [% select_fields.resolution.json_visibility %];
</script>
[%# Common actions %]
@ -149,7 +149,7 @@
<option selected value="[% bug.bug_status FILTER html %]">
[% get_status(bug.bug_status) FILTER html %]
</option>
[% IF !bug.isopened %]
[% IF !bug.isopened %]
[% show_resolution = 1 %]
[% filtered_status = bug.bug_status FILTER js %]
[% closed_status_array.push(filtered_status) %]

View File

@ -358,18 +358,16 @@
[% IF value.visibility_values.size > 0 %]
<li>It only appears when
[%+ value.field.value_field.description | html %] is set to
[% SET vv_i = 0 %]
[% FOR vv = value.visibility_values %]
[% IF vv_i %] or [% END %]
'[%+ vv.name | html %]'
[% SET vv_i = vv_i+1 %]
'[%+ vv.name | html %]'
[% " or " UNLESS loop.last %]
[% END %]
</li>
[% ELSE %]
<li>It now always appears, no matter what
[%+ value.field.value_field.description | html %] is set to.
</li>
[% END %]
[% END %]
[% END %]
</ul>
[% ELSE %]

View File

@ -37,11 +37,11 @@ use Testopia::Constants;
###############################################################################
# tr_new_plan.cgi
# Presents a webform to the user for the creation of a new test plan.
# Creates a new testplan via Ajax
# Presents a webform to the user for the creation of a new test plan.
# Creates a new testplan via Ajax
#
# INTERFACE:
# action:
# action:
# undef - Present form for new plan creation
# "add" - Form has been submitted with plan data. Create the test
# plan.
@ -55,7 +55,7 @@ use Testopia::Constants;
# file_desc1-5: string - (OPTIONAL) Description of file to attach
#
#
################################################################################
################################################################################
my $vars = {};
my $template = Bugzilla->template;
@ -70,20 +70,20 @@ my $action = $cgi->param('action') || '';
if ($action eq 'add'){
Bugzilla->error_mode(ERROR_MODE_AJAX);
ThrowUserError("testopia-create-denied", {'object' => 'Test Plan'}) unless Bugzilla->user->in_group('Testers');
my $plan = Testopia::TestPlan->create({
'product_id' => $cgi->param('product_id'),
'author_id' => Bugzilla->user->id,
'type_id' => $cgi->param('type'),
'default_product_version' => $cgi->param('prod_version'),
'name' => $cgi->param('plan_name'),
'text' => $cgi->param("plandoc") || '',
'product_id' => $cgi->param('product_id'),
'author_id' => Bugzilla->user->id,
'type_id' => $cgi->param('type'),
'default_product_version' => $cgi->param('prod_version'),
'name' => $cgi->param('plan_name'),
'text' => $cgi->param("plandoc") || '',
});
my $err = JSON::false;
for (my $i=1; $i<5; $i++){
next unless defined $cgi->upload("file$i");
my $fh = $cgi->upload("file$i");
my $data;
# enable 'slurp' mode
@ -94,19 +94,19 @@ if ($action eq 'add'){
Bugzilla->error_mode(ERROR_MODE_DIE);
eval {
my $attachment = Testopia::Attachment->create({
plan_id => $plan->id,
submitter_id => Bugzilla->user->id,
description => $cgi->param("file_desc$i") || 'Attachment',
filename => $cgi->upload("file$i"),
mime_type => $cgi->uploadInfo($cgi->param("file$i"))->{'Content-Type'},
contents => $data
plan_id => $plan->id,
submitter_id => Bugzilla->user->id,
description => $cgi->param("file_desc$i") || 'Attachment',
filename => $cgi->upload("file$i"),
mime_type => $cgi->uploadInfo($cgi->param("file$i"))->{'Content-Type'},
contents => $data
});
};
if ($@){
$err = JSON::true;
}
}
print "{success: true, plan: '". $plan->id ."', err: $err}";
}
@ -121,7 +121,7 @@ else {
ThrowUserError('testopia-read-only', {'object' => $product}) unless $product->canedit;
$vars->{'product'} = $product;
}
ThrowUserError("testopia-create-denied", {'object' => 'Test Plan'}) unless Bugzilla->user->in_group('Testers');
$vars->{'plan'} = Testopia::TestPlan->new({});
$template->process("testopia/plan/add.html.tmpl", $vars) ||