Allow to enable/disable empty version/milestone from the product page

hinted-selects
Vitaliy Filippov 2014-06-27 19:22:25 +04:00
parent b00b5c23d0
commit 4f20f1242c
5 changed files with 100 additions and 5 deletions

View File

@ -195,7 +195,7 @@ use constant DEFAULT_FIELDS => (map { my $i = 0; $_ = { (map { (DEFAULT_FIELD_CO
[ 'attachments.isprivate', 'Attachment is private', 0, 0, 0 ],
[ 'attachments.submitter', 'Attachment creator', 0, 0, 0 ],
[ 'target_milestone', 'Target Milestone', 0, 1, 1, FIELD_TYPE_SINGLE_SELECT, 'product' ],
[ 'target_milestone', 'Target Milestone', 0, 1, 1, FIELD_TYPE_SINGLE_SELECT, 'product', 'product' ],
[ 'creation_ts', 'Creation time', 1, 0, 0, FIELD_TYPE_DATETIME ],
[ 'delta_ts', 'Last changed time', 1, 0, 0, FIELD_TYPE_DATETIME ],
[ 'longdesc', 'Comment', 0, 0, 0 ],
@ -1278,13 +1278,55 @@ sub update_visibility_values
return 1;
}
# FIXME Вот такая у нас сейчас логика... не нравится она мне... Скорее всего, надо делать так:
# * если записей нет, а visibility_field_id есть - поле не видно никогда. новые поля не видны нигде.
# * аналогично со значениями; новые значения не видны нигде.
# * придётся добавить ещё null_field_id, т.к. например target_milestone может быть виден везде, а nullable быть не везде
# * отдельное поле, от которого зависит дефолтное значение (default_field_id), отдельная таблица
# для хранения дефолтных значений (field_id, visibility_value_id, default_value). Т.к. это не только для select'ов...
# (тут точно нужно отдельное поле, т.к. например наборы версий зависят от продукта, но дефолтные версии - от компонента)
# * и видимо отдельное поле, от которого зависит клонирование (clone_field_id), и хранить (field_id, -2, visibility_value_id)
sub toggle_value
{
my ($f, $v, $vv, $enable) = @_;
my ($any, $this) = Bugzilla->dbh->selectrow_array(
'SELECT COUNT(*), SUM(visibility_value_id=?) FROM fieldvaluecontrol WHERE field_id=? AND value_id=?', undef, $vv, $f, $v
);
if ($enable && $any && !$this)
{
Bugzilla->dbh->do('INSERT INTO fieldvaluecontrol (field_id, value_id, visibility_value_id) VALUES (?, ?, ?)', undef, $f, $v, $vv);
return 1;
}
elsif (!$enable && !$any)
{
my $obj = Bugzilla->get_field($f);
$obj = $v > 0 ? $obj->value_field : $obj->visibility_field;
# FIXME: Taint bug (5.18.2): $obj->value_type->DB_TABLE becomes tainted
# and taints SQL query if substituted directly into dbh->do()...
my $t = $obj->value_type->DB_TABLE;
Bugzilla->dbh->do(
'INSERT INTO fieldvaluecontrol (field_id, value_id, visibility_value_id)'.
'SELECT ?, ?, id FROM '.$t.' WHERE id != ?',
undef, $f, $v, $vv
);
return 0;
}
elsif (!$enable && $this)
{
Bugzilla->dbh->do(
'DELETE FROM fieldvaluecontrol WHERE field_id=? AND value_id=? AND visibility_value_id=?',
undef, $f, $v, $vv
);
return 0;
}
return undef;
}
sub update_controlled_values
{
my ($controlled_field, $controlled_value_ids, $visibility_value_id, $default_value_ids) = @_;
$controlled_value_ids ||= [];
my $vis_field = $controlled_value_ids
? $controlled_field->value_field
: $controlled_field->visibility_field;
my $vis_field = $controlled_field->value_field;
if (!$vis_field)
{
return undef;
@ -1305,7 +1347,6 @@ sub update_controlled_values
$controlled_value_ids = [ map { $_->id } @{ $type->new_from_list($controlled_value_ids) } ];
if ($default_value_ids)
{
my $type = Bugzilla::Field::Choice->type($controlled_field);
$default_value_ids = { map { $_->id => 1 } @{ $type->new_from_list($default_value_ids) } };
}
my $f = $controlled_field->id;

View File

@ -77,6 +77,11 @@ no warnings 'redefine';
eval { require 'Lingua/Stem/Snowball.pm' };
sub is_tainted
{
return !eval { join('', @_), kill 0; 1; };
}
sub trick_taint
{
return undef unless defined $_[0];

View File

@ -292,6 +292,15 @@ if ($action eq 'edit' || (!$action && $product_name))
my $length = values %$controlled_fields;
$vars->{controlled_field_names} = $length > 0 ? join(', ', values %$controlled_fields) : 'No fields';
for (qw(version target_milestone))
{
my $f = Bugzilla->get_field($_);
if ($vars->{'allow_nullable_'.$f->name} = $f->nullable)
{
my $null = $f->null_visibility_values;
$vars->{$f->name.'_is_nullable'} = !$null || $null->{$product->id};
}
}
$vars->{all_groups} = [ map { $_->name } Bugzilla::Group->get_all ];
$template->process('admin/products/edit.html.tmpl', $vars)
@ -331,6 +340,18 @@ if ($action eq 'update')
my $changes = $product->update();
for (qw(version target_milestone))
{
my $f = Bugzilla->get_field($_);
if ($f->nullable)
{
my $c = Bugzilla::Field::toggle_value(
$f->id, -1, $product->id, scalar $cgi->param($f->name.'_is_nullable')
);
$changes->{$f->name.'_is_nullable'} = [ !$c, $c ] if defined $c;
}
}
delete_token($token);
if (Bugzilla->params->{useclassification})

View File

@ -79,6 +79,26 @@
[% END %]
</td>
</tr>
[% IF allow_nullable_version %]
<tr>
<th align="left" valign="top">
<label for="version_is_nullable">Allow empty Version:</label>
</th>
<td>
<input type="checkbox" name="version_is_nullable" id="version_is_nullable" value="1" [% " checked" IF version_is_nullable %] />
</td>
</tr>
[% END %]
[% IF allow_nullable_target_milestone %]
<tr>
<th align="left" valign="top">
<label for="target_milestone_is_nullable">Allow empty Target Milestone:</label>
</th>
<td>
<input type="checkbox" name="target_milestone_is_nullable" id="target_milestone_is_nullable" value="1" [% " checked" IF target_milestone_is_nullable %] />
</td>
</tr>
[% END %]
[% IF Param('usetargetmilestone') %]
<tr>
<th align="left" valign="top">

View File

@ -137,6 +137,14 @@
<p>External product is [% IF changes.extproduct %]set to [% product.extproduct_obj.name | html %][% ELSE %]cleared[% END %].</p>
[% END %]
[% IF changes.version_is_nullable.defined %]
<p>Empty version [% changes.version_is_nullable.1 ? 'enabled' : 'disabled' %].</p>
[% END %]
[% IF changes.target_milestone_is_nullable.defined %]
<p>Empty milestone [% changes.target_milestone_is_nullable.1 ? 'enabled' : 'disabled' %].</p>
[% END %]
[% IF !changes.keys.size %]
<p>Nothing changed for product '[% product.name FILTER html %]'.</p>
[% END %]