Allow to enable/disable empty version/milestone from the product page
parent
b00b5c23d0
commit
4f20f1242c
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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 %]
|
||||
|
|
Loading…
Reference in New Issue