зеркало из https://github.com/mozilla/gecko-dev.git
Bug 299753: Replace old code in editproducts.cgi by routines from Product.pm - Patch by Andr� Batosti <batosti@async.com.br> r=LpSolit a=justdave
This commit is contained in:
Родитель
b9f159aee3
Коммит
d08f38656a
|
@ -187,6 +187,20 @@ sub bug_count {
|
||||||
return $self->{'bug_count'};
|
return $self->{'bug_count'};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub bug_ids {
|
||||||
|
my $self = shift;
|
||||||
|
my $dbh = Bugzilla->dbh;
|
||||||
|
|
||||||
|
if (!defined $self->{'bug_ids'}) {
|
||||||
|
$self->{'bug_ids'} =
|
||||||
|
$dbh->selectcol_arrayref(q{SELECT bug_id FROM bugs
|
||||||
|
WHERE product_id = ?},
|
||||||
|
undef, $self->id);
|
||||||
|
}
|
||||||
|
return $self->{'bug_ids'};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
#### Accessors ######
|
#### Accessors ######
|
||||||
###############################
|
###############################
|
||||||
|
@ -253,6 +267,7 @@ Bugzilla::Product - Bugzilla product class.
|
||||||
my @milestones = $product->milestones();
|
my @milestones = $product->milestones();
|
||||||
my @versions = $product->versions();
|
my @versions = $product->versions();
|
||||||
my $bugcount = $product->bug_count();
|
my $bugcount = $product->bug_count();
|
||||||
|
my $bug_ids = $product->bug_ids();
|
||||||
|
|
||||||
my $id = $product->id;
|
my $id = $product->id;
|
||||||
my $name = $product->name;
|
my $name = $product->name;
|
||||||
|
@ -330,6 +345,14 @@ Product.pm represents a product object.
|
||||||
|
|
||||||
Returns: Integer with the number of bugs.
|
Returns: Integer with the number of bugs.
|
||||||
|
|
||||||
|
=item C<bug_ids()>
|
||||||
|
|
||||||
|
Description: Returns the IDs of bugs that belong to the product.
|
||||||
|
|
||||||
|
Params: none.
|
||||||
|
|
||||||
|
Returns: An array of integer.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 SUBROUTINES
|
=head1 SUBROUTINES
|
||||||
|
|
|
@ -38,94 +38,14 @@ require "globals.pl";
|
||||||
use Bugzilla::Bug;
|
use Bugzilla::Bug;
|
||||||
use Bugzilla::Series;
|
use Bugzilla::Series;
|
||||||
use Bugzilla::Config qw(:DEFAULT $datadir);
|
use Bugzilla::Config qw(:DEFAULT $datadir);
|
||||||
|
use Bugzilla::Product;
|
||||||
|
use Bugzilla::Classification;
|
||||||
|
use Bugzilla::Milestone;
|
||||||
|
|
||||||
# Shut up misguided -w warnings about "used only once". "use vars" just
|
# Shut up misguided -w warnings about "used only once". "use vars" just
|
||||||
# doesn't work for me.
|
# doesn't work for me.
|
||||||
use vars qw(@legal_bug_status @legal_resolution);
|
use vars qw(@legal_bug_status @legal_resolution);
|
||||||
|
|
||||||
# TestProduct: just returns if the specified product does exists
|
|
||||||
# CheckProduct: same check, optionally emit an error text
|
|
||||||
|
|
||||||
sub TestProduct
|
|
||||||
{
|
|
||||||
my $prod = shift;
|
|
||||||
|
|
||||||
# does the product exist?
|
|
||||||
SendSQL("SELECT name
|
|
||||||
FROM products
|
|
||||||
WHERE name=" . SqlQuote($prod));
|
|
||||||
return FetchOneColumn();
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckProduct
|
|
||||||
{
|
|
||||||
my $prod = shift;
|
|
||||||
|
|
||||||
# do we have a product?
|
|
||||||
unless ($prod) {
|
|
||||||
ThrowUserError('product_not_specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
unless (TestProduct($prod)) {
|
|
||||||
ThrowUserError('product_doesnt_exist',
|
|
||||||
{'product' => $prod});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# TestClassification: just returns if the specified classification does exists
|
|
||||||
# CheckClassification: same check, optionally emit an error text
|
|
||||||
|
|
||||||
sub TestClassification
|
|
||||||
{
|
|
||||||
my $cl = shift;
|
|
||||||
|
|
||||||
# does the classification exist?
|
|
||||||
SendSQL("SELECT name
|
|
||||||
FROM classifications
|
|
||||||
WHERE name=" . SqlQuote($cl));
|
|
||||||
return FetchOneColumn();
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckClassification
|
|
||||||
{
|
|
||||||
my $cl = shift;
|
|
||||||
|
|
||||||
# do we have a classification?
|
|
||||||
unless ($cl) {
|
|
||||||
ThrowUserError('classification_not_specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
unless (TestClassification($cl)) {
|
|
||||||
ThrowUserError('classification_doesnt_exist',
|
|
||||||
{'name' => $cl});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub CheckClassificationProduct
|
|
||||||
{
|
|
||||||
my ($cl, $prod) = @_;
|
|
||||||
my $dbh = Bugzilla->dbh;
|
|
||||||
|
|
||||||
CheckClassification($cl);
|
|
||||||
|
|
||||||
trick_taint($prod);
|
|
||||||
trick_taint($cl);
|
|
||||||
|
|
||||||
my ($res) = $dbh->selectrow_array(q{
|
|
||||||
SELECT products.name
|
|
||||||
FROM products
|
|
||||||
INNER JOIN classifications
|
|
||||||
ON products.classification_id = classifications.id
|
|
||||||
WHERE products.name = ? AND classifications.name = ?},
|
|
||||||
undef, ($prod, $cl));
|
|
||||||
|
|
||||||
unless ($res) {
|
|
||||||
ThrowUserError('classification_doesnt_exist_for_product',
|
|
||||||
{ product => $prod, classification => $cl });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Preliminary checks:
|
# Preliminary checks:
|
||||||
#
|
#
|
||||||
|
@ -144,8 +64,8 @@ $user->in_group('editcomponents')
|
||||||
#
|
#
|
||||||
# often used variables
|
# often used variables
|
||||||
#
|
#
|
||||||
my $classification = trim($cgi->param('classification') || '');
|
my $classification_name = trim($cgi->param('classification') || '');
|
||||||
my $product = trim($cgi->param('product') || '');
|
my $product_name = trim($cgi->param('product') || '');
|
||||||
my $action = trim($cgi->param('action') || '');
|
my $action = trim($cgi->param('action') || '');
|
||||||
my $dbh = Bugzilla->dbh;
|
my $dbh = Bugzilla->dbh;
|
||||||
|
|
||||||
|
@ -155,22 +75,13 @@ my $dbh = Bugzilla->dbh;
|
||||||
#
|
#
|
||||||
|
|
||||||
if (Param('useclassification')
|
if (Param('useclassification')
|
||||||
&& !$classification
|
&& !$classification_name
|
||||||
&& !$product)
|
&& !$product_name)
|
||||||
{
|
{
|
||||||
my $query =
|
my @classifications =
|
||||||
"SELECT classifications.name, classifications.description,
|
Bugzilla::Classification::get_all_classifications();
|
||||||
COUNT(classification_id) AS product_count
|
|
||||||
FROM classifications
|
|
||||||
LEFT JOIN products
|
|
||||||
ON classifications.id = products.classification_id " .
|
|
||||||
$dbh->sql_group_by('classifications.id',
|
|
||||||
'classifications.name,
|
|
||||||
classifications.description') . "
|
|
||||||
ORDER BY name";
|
|
||||||
|
|
||||||
$vars->{'classifications'} = $dbh->selectall_arrayref($query,
|
$vars->{'classifications'} = \@classifications;
|
||||||
{'Slice' => {}});
|
|
||||||
|
|
||||||
$template->process("admin/products/list-classifications.html.tmpl",
|
$template->process("admin/products/list-classifications.html.tmpl",
|
||||||
$vars)
|
$vars)
|
||||||
|
@ -185,50 +96,21 @@ if (Param('useclassification')
|
||||||
# is already specified (then edit it)
|
# is already specified (then edit it)
|
||||||
#
|
#
|
||||||
|
|
||||||
if (!$action && !$product) {
|
if (!$action && !$product_name) {
|
||||||
|
my @products;
|
||||||
|
|
||||||
if (Param('useclassification')) {
|
if (Param('useclassification')) {
|
||||||
CheckClassification($classification);
|
my $classification =
|
||||||
}
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
|
|
||||||
my @execute_params = ();
|
|
||||||
my @products = ();
|
|
||||||
|
|
||||||
my $query = "SELECT products.name,
|
|
||||||
COALESCE(products.description,'') AS description,
|
|
||||||
disallownew = 0 AS status,
|
|
||||||
votesperuser, maxvotesperbug, votestoconfirm,
|
|
||||||
COUNT(bug_id) AS bug_count
|
|
||||||
FROM products";
|
|
||||||
|
|
||||||
if (Param('useclassification')) {
|
|
||||||
$query .= " INNER JOIN classifications " .
|
|
||||||
"ON classifications.id = products.classification_id";
|
|
||||||
}
|
|
||||||
|
|
||||||
$query .= " LEFT JOIN bugs ON products.id = bugs.product_id";
|
|
||||||
|
|
||||||
if (Param('useclassification')) {
|
|
||||||
$query .= " WHERE classifications.name = ? ";
|
|
||||||
|
|
||||||
# trick_taint is OK because we use this in a placeholder in a SELECT
|
|
||||||
trick_taint($classification);
|
|
||||||
|
|
||||||
push(@execute_params,
|
|
||||||
$classification);
|
|
||||||
}
|
|
||||||
|
|
||||||
$query .= " " . $dbh->sql_group_by('products.name',
|
|
||||||
'products.description, disallownew,
|
|
||||||
votesperuser, maxvotesperbug,
|
|
||||||
votestoconfirm');
|
|
||||||
$query .= " ORDER BY products.name";
|
|
||||||
|
|
||||||
$vars->{'products'} = $dbh->selectall_arrayref($query,
|
|
||||||
{'Slice' => {}},
|
|
||||||
@execute_params);
|
|
||||||
|
|
||||||
|
@products = @{$classification->products};
|
||||||
$vars->{'classification'} = $classification;
|
$vars->{'classification'} = $classification;
|
||||||
|
} else {
|
||||||
|
@products = Bugzilla::Product::get_all_products;
|
||||||
|
}
|
||||||
|
|
||||||
|
$vars->{'products'} = \@products;
|
||||||
|
|
||||||
$template->process("admin/products/list.html.tmpl",
|
$template->process("admin/products/list.html.tmpl",
|
||||||
$vars)
|
$vars)
|
||||||
|| ThrowTemplateError($template->error());
|
|| ThrowTemplateError($template->error());
|
||||||
|
@ -248,9 +130,10 @@ if (!$action && !$product) {
|
||||||
if ($action eq 'add') {
|
if ($action eq 'add') {
|
||||||
|
|
||||||
if (Param('useclassification')) {
|
if (Param('useclassification')) {
|
||||||
CheckClassification($classification);
|
my $classification =
|
||||||
}
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
$vars->{'classification'} = $classification;
|
$vars->{'classification'} = $classification;
|
||||||
|
}
|
||||||
$template->process("admin/products/create.html.tmpl", $vars)
|
$template->process("admin/products/create.html.tmpl", $vars)
|
||||||
|| ThrowTemplateError($template->error());
|
|| ThrowTemplateError($template->error());
|
||||||
|
|
||||||
|
@ -268,30 +151,31 @@ if ($action eq 'new') {
|
||||||
|
|
||||||
my $classification_id = 1;
|
my $classification_id = 1;
|
||||||
if (Param('useclassification')) {
|
if (Param('useclassification')) {
|
||||||
CheckClassification($classification);
|
my $classification =
|
||||||
$classification_id = get_classification_id($classification);
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
|
$classification_id = $classification->id;
|
||||||
$vars->{'classification'} = $classification;
|
$vars->{'classification'} = $classification;
|
||||||
}
|
}
|
||||||
|
|
||||||
unless ($product) {
|
unless ($product_name) {
|
||||||
ThrowUserError("product_blank_name");
|
ThrowUserError("product_blank_name");
|
||||||
}
|
}
|
||||||
|
|
||||||
my $existing_product = TestProduct($product);
|
my $product = new Bugzilla::Product({name => $product_name});
|
||||||
|
|
||||||
if ($existing_product) {
|
if ($product) {
|
||||||
|
|
||||||
# Check for exact case sensitive match:
|
# Check for exact case sensitive match:
|
||||||
if ($existing_product eq $product) {
|
if ($product->name eq $product_name) {
|
||||||
ThrowUserError("prod_name_already_in_use",
|
ThrowUserError("prod_name_already_in_use",
|
||||||
{'product' => $product});
|
{'product' => $product->name});
|
||||||
}
|
}
|
||||||
|
|
||||||
# Next check for a case-insensitive match:
|
# Next check for a case-insensitive match:
|
||||||
if (lc($existing_product) eq lc($product)) {
|
if (lc($product->name) eq lc($product_name)) {
|
||||||
ThrowUserError("prod_name_diff_in_case",
|
ThrowUserError("prod_name_diff_in_case",
|
||||||
{'product' => $product,
|
{'product' => $product_name,
|
||||||
'existing_product' => $existing_product});
|
'existing_product' => $product->name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,14 +183,14 @@ if ($action eq 'new') {
|
||||||
|
|
||||||
if ($version eq '') {
|
if ($version eq '') {
|
||||||
ThrowUserError("product_must_have_version",
|
ThrowUserError("product_must_have_version",
|
||||||
{'product' => $product});
|
{'product' => $product_name});
|
||||||
}
|
}
|
||||||
|
|
||||||
my $description = trim($cgi->param('description') || '');
|
my $description = trim($cgi->param('description') || '');
|
||||||
|
|
||||||
if ($description eq '') {
|
if ($description eq '') {
|
||||||
ThrowUserError('product_must_have_description',
|
ThrowUserError('product_must_have_description',
|
||||||
{'product' => $product});
|
{'product' => $product_name});
|
||||||
}
|
}
|
||||||
|
|
||||||
my $milestoneurl = trim($cgi->param('milestoneurl') || '');
|
my $milestoneurl = trim($cgi->param('milestoneurl') || '');
|
||||||
|
@ -325,7 +209,7 @@ if ($action eq 'new') {
|
||||||
"name, description, milestoneurl, disallownew, votesperuser, " .
|
"name, description, milestoneurl, disallownew, votesperuser, " .
|
||||||
"maxvotesperbug, votestoconfirm, defaultmilestone, classification_id" .
|
"maxvotesperbug, votestoconfirm, defaultmilestone, classification_id" .
|
||||||
" ) VALUES ( " .
|
" ) VALUES ( " .
|
||||||
SqlQuote($product) . "," .
|
SqlQuote($product_name) . "," .
|
||||||
SqlQuote($description) . "," .
|
SqlQuote($description) . "," .
|
||||||
SqlQuote($milestoneurl) . "," .
|
SqlQuote($milestoneurl) . "," .
|
||||||
# had tainting issues under cygwin, IIS 5.0, perl -T %s %s
|
# had tainting issues under cygwin, IIS 5.0, perl -T %s %s
|
||||||
|
@ -339,22 +223,23 @@ if ($action eq 'new') {
|
||||||
SqlQuote($votestoconfirm) . "," .
|
SqlQuote($votestoconfirm) . "," .
|
||||||
SqlQuote($defaultmilestone) . "," .
|
SqlQuote($defaultmilestone) . "," .
|
||||||
SqlQuote($classification_id) . ")");
|
SqlQuote($classification_id) . ")");
|
||||||
my $product_id = $dbh->bz_last_key('products', 'id');
|
|
||||||
|
$product = new Bugzilla::Product({name => $product_name});
|
||||||
|
|
||||||
SendSQL("INSERT INTO versions ( " .
|
SendSQL("INSERT INTO versions ( " .
|
||||||
"value, product_id" .
|
"value, product_id" .
|
||||||
" ) VALUES ( " .
|
" ) VALUES ( " .
|
||||||
SqlQuote($version) . "," .
|
SqlQuote($version) . "," .
|
||||||
$product_id . ")" );
|
$product->id . ")" );
|
||||||
|
|
||||||
SendSQL("INSERT INTO milestones (product_id, value) VALUES (" .
|
SendSQL("INSERT INTO milestones (product_id, value) VALUES (" .
|
||||||
$product_id . ", " . SqlQuote($defaultmilestone) . ")");
|
$product->id . ", " . SqlQuote($defaultmilestone) . ")");
|
||||||
|
|
||||||
# If we're using bug groups, then we need to create a group for this
|
# If we're using bug groups, then we need to create a group for this
|
||||||
# product as well. -JMR, 2/16/00
|
# product as well. -JMR, 2/16/00
|
||||||
if (Param("makeproductgroups")) {
|
if (Param("makeproductgroups")) {
|
||||||
# Next we insert into the groups table
|
# Next we insert into the groups table
|
||||||
my $productgroup = $product;
|
my $productgroup = $product->name;
|
||||||
while (GroupExists($productgroup)) {
|
while (GroupExists($productgroup)) {
|
||||||
$productgroup .= '_';
|
$productgroup .= '_';
|
||||||
}
|
}
|
||||||
|
@ -362,7 +247,8 @@ if ($action eq 'new') {
|
||||||
"(name, description, isbuggroup, last_changed) " .
|
"(name, description, isbuggroup, last_changed) " .
|
||||||
"VALUES (" .
|
"VALUES (" .
|
||||||
SqlQuote($productgroup) . ", " .
|
SqlQuote($productgroup) . ", " .
|
||||||
SqlQuote("Access to bugs in the $product product") . ", 1, NOW())");
|
SqlQuote("Access to bugs in the " . $product->name .
|
||||||
|
" product") . ", 1, NOW())");
|
||||||
my $gid = $dbh->bz_last_key('groups', 'id');
|
my $gid = $dbh->bz_last_key('groups', 'id');
|
||||||
my $admin = GroupNameToId('admin');
|
my $admin = GroupNameToId('admin');
|
||||||
# If we created a new group, give the "admin" group priviledges
|
# If we created a new group, give the "admin" group priviledges
|
||||||
|
@ -378,7 +264,8 @@ if ($action eq 'new') {
|
||||||
SendSQL("INSERT INTO group_control_map " .
|
SendSQL("INSERT INTO group_control_map " .
|
||||||
"(group_id, product_id, entry, " .
|
"(group_id, product_id, entry, " .
|
||||||
"membercontrol, othercontrol, canedit) VALUES " .
|
"membercontrol, othercontrol, canedit) VALUES " .
|
||||||
"($gid, $product_id, " . Param("useentrygroupdefault") .
|
"($gid, " . $product->id . ", " .
|
||||||
|
Param("useentrygroupdefault") .
|
||||||
", " . CONTROLMAPDEFAULT . ", " .
|
", " . CONTROLMAPDEFAULT . ", " .
|
||||||
CONTROLMAPNA . ", 0)");
|
CONTROLMAPNA . ", 0)");
|
||||||
}
|
}
|
||||||
|
@ -392,7 +279,6 @@ if ($action eq 'new') {
|
||||||
# and never used again here, so we can trick_taint them.
|
# and never used again here, so we can trick_taint them.
|
||||||
my $open_name = $cgi->param('open_name');
|
my $open_name = $cgi->param('open_name');
|
||||||
trick_taint($open_name);
|
trick_taint($open_name);
|
||||||
trick_taint($product);
|
|
||||||
|
|
||||||
my @series;
|
my @series;
|
||||||
|
|
||||||
|
@ -415,10 +301,11 @@ if ($action eq 'new') {
|
||||||
push(@series, [$open_name, $query]);
|
push(@series, [$open_name, $query]);
|
||||||
|
|
||||||
foreach my $sdata (@series) {
|
foreach my $sdata (@series) {
|
||||||
my $series = new Bugzilla::Series(undef, $product,
|
my $series = new Bugzilla::Series(undef, $product->name,
|
||||||
scalar $cgi->param('subcategory'),
|
scalar $cgi->param('subcategory'),
|
||||||
$sdata->[0], $::userid, 1,
|
$sdata->[0], $::userid, 1,
|
||||||
$sdata->[1] . "&product=" . url_quote($product), 1);
|
$sdata->[1] . "&product=" .
|
||||||
|
url_quote($product->name), 1);
|
||||||
$series->writeToDatabase();
|
$series->writeToDatabase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,6 +313,7 @@ if ($action eq 'new') {
|
||||||
unlink "$datadir/versioncache";
|
unlink "$datadir/versioncache";
|
||||||
|
|
||||||
$vars->{'product'} = $product;
|
$vars->{'product'} = $product;
|
||||||
|
|
||||||
$template->process("admin/products/created.html.tmpl", $vars)
|
$template->process("admin/products/created.html.tmpl", $vars)
|
||||||
|| ThrowTemplateError($template->error());
|
|| ThrowTemplateError($template->error());
|
||||||
exit;
|
exit;
|
||||||
|
@ -439,67 +327,20 @@ if ($action eq 'new') {
|
||||||
|
|
||||||
if ($action eq 'del') {
|
if ($action eq 'del') {
|
||||||
|
|
||||||
if (!$product) {
|
my $product = Bugzilla::Product::check_product($product_name);
|
||||||
ThrowUserError('product_not_specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $product_id = get_product_id($product);
|
|
||||||
$product_id || ThrowUserError('product_doesnt_exist',
|
|
||||||
{product => $product});
|
|
||||||
|
|
||||||
my $classification_id = 1;
|
|
||||||
|
|
||||||
if (Param('useclassification')) {
|
if (Param('useclassification')) {
|
||||||
CheckClassificationProduct($classification, $product);
|
my $classification =
|
||||||
$classification_id = get_classification_id($classification);
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
|
if ($classification->id != $product->classification_id) {
|
||||||
|
ThrowUserError('classification_doesnt_exist_for_product',
|
||||||
|
{ product => $product->name,
|
||||||
|
classification => $classification->name });
|
||||||
|
}
|
||||||
$vars->{'classification'} = $classification;
|
$vars->{'classification'} = $classification;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Extract some data about the product
|
$vars->{'product'} = $product;
|
||||||
my $query = q{SELECT classifications.description,
|
|
||||||
products.description,
|
|
||||||
products.milestoneurl,
|
|
||||||
products.disallownew
|
|
||||||
FROM products
|
|
||||||
INNER JOIN classifications
|
|
||||||
ON products.classification_id = classifications.id
|
|
||||||
WHERE products.id = ?};
|
|
||||||
|
|
||||||
my ($class_description,
|
|
||||||
$prod_description,
|
|
||||||
$milestoneurl,
|
|
||||||
$disallownew) = $dbh->selectrow_array($query, undef,
|
|
||||||
$product_id);
|
|
||||||
|
|
||||||
$vars->{'class_description'} = $class_description;
|
|
||||||
$vars->{'product_id'} = $product_id;
|
|
||||||
$vars->{'prod_description'} = $prod_description;
|
|
||||||
$vars->{'milestoneurl'} = $milestoneurl;
|
|
||||||
$vars->{'disallownew'} = $disallownew;
|
|
||||||
$vars->{'product_name'} = $product;
|
|
||||||
|
|
||||||
$vars->{'components'} = $dbh->selectall_arrayref(q{
|
|
||||||
SELECT name, description FROM components
|
|
||||||
WHERE product_id = ? ORDER BY name}, {'Slice' => {}},
|
|
||||||
$product_id);
|
|
||||||
|
|
||||||
$vars->{'versions'} = $dbh->selectcol_arrayref(q{
|
|
||||||
SELECT value FROM versions
|
|
||||||
WHERE product_id = ? ORDER BY value}, undef,
|
|
||||||
$product_id);
|
|
||||||
|
|
||||||
# Adding listing for associated target milestones -
|
|
||||||
# matthew@zeroknowledge.com
|
|
||||||
if (Param('usetargetmilestone')) {
|
|
||||||
$vars->{'milestones'} = $dbh->selectcol_arrayref(q{
|
|
||||||
SELECT value FROM milestones
|
|
||||||
WHERE product_id = ?
|
|
||||||
ORDER BY sortkey, value}, undef, $product_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
($vars->{'bug_count'}) = $dbh->selectrow_array(q{
|
|
||||||
SELECT COUNT(*) FROM bugs WHERE product_id = ?},
|
|
||||||
undef, $product_id) || 0;
|
|
||||||
|
|
||||||
$template->process("admin/products/confirm-delete.html.tmpl", $vars)
|
$template->process("admin/products/confirm-delete.html.tmpl", $vars)
|
||||||
|| ThrowTemplateError($template->error());
|
|| ThrowTemplateError($template->error());
|
||||||
|
@ -512,33 +353,32 @@ if ($action eq 'del') {
|
||||||
|
|
||||||
if ($action eq 'delete') {
|
if ($action eq 'delete') {
|
||||||
|
|
||||||
if (!$product) {
|
my $product = Bugzilla::Product::check_product($product_name);
|
||||||
ThrowUserError('product_not_specified');
|
|
||||||
}
|
|
||||||
|
|
||||||
my $product_id = get_product_id($product);
|
|
||||||
$product_id || ThrowUserError('product_doesnt_exist',
|
|
||||||
{product => $product});
|
|
||||||
|
|
||||||
$vars->{'product'} = $product;
|
$vars->{'product'} = $product;
|
||||||
|
|
||||||
|
if (Param('useclassification')) {
|
||||||
|
my $classification =
|
||||||
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
|
if ($classification->id != $product->classification_id) {
|
||||||
|
ThrowUserError('classification_doesnt_exist_for_product',
|
||||||
|
{ product => $product->name,
|
||||||
|
classification => $classification->name });
|
||||||
|
}
|
||||||
$vars->{'classification'} = $classification;
|
$vars->{'classification'} = $classification;
|
||||||
|
}
|
||||||
|
|
||||||
my $bug_ids = $dbh->selectcol_arrayref(q{
|
if ($product->bug_count) {
|
||||||
SELECT bug_id FROM bugs
|
|
||||||
WHERE product_id = ?}, undef, $product_id);
|
|
||||||
|
|
||||||
my $nb_bugs = scalar(@$bug_ids);
|
|
||||||
if ($nb_bugs) {
|
|
||||||
if (Param("allowbugdeletion")) {
|
if (Param("allowbugdeletion")) {
|
||||||
foreach my $bug_id (@$bug_ids) {
|
foreach my $bug_id (@{$product->bug_ids}) {
|
||||||
my $bug = new Bugzilla::Bug($bug_id, $whoid);
|
my $bug = new Bugzilla::Bug($bug_id, $whoid);
|
||||||
$bug->remove_from_db();
|
$bug->remove_from_db();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ThrowUserError("product_has_bugs", { nb => $nb_bugs });
|
ThrowUserError("product_has_bugs",
|
||||||
|
{ nb => $product->bug_count });
|
||||||
}
|
}
|
||||||
$vars->{'nb_bugs'} = $nb_bugs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$dbh->bz_lock_tables('products WRITE', 'components WRITE',
|
$dbh->bz_lock_tables('products WRITE', 'components WRITE',
|
||||||
|
@ -547,25 +387,25 @@ if ($action eq 'delete') {
|
||||||
'flaginclusions WRITE', 'flagexclusions WRITE');
|
'flaginclusions WRITE', 'flagexclusions WRITE');
|
||||||
|
|
||||||
$dbh->do("DELETE FROM components WHERE product_id = ?",
|
$dbh->do("DELETE FROM components WHERE product_id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->do("DELETE FROM versions WHERE product_id = ?",
|
$dbh->do("DELETE FROM versions WHERE product_id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->do("DELETE FROM milestones WHERE product_id = ?",
|
$dbh->do("DELETE FROM milestones WHERE product_id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->do("DELETE FROM group_control_map WHERE product_id = ?",
|
$dbh->do("DELETE FROM group_control_map WHERE product_id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->do("DELETE FROM flaginclusions WHERE product_id = ?",
|
$dbh->do("DELETE FROM flaginclusions WHERE product_id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->do("DELETE FROM flagexclusions WHERE product_id = ?",
|
$dbh->do("DELETE FROM flagexclusions WHERE product_id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->do("DELETE FROM products WHERE id = ?",
|
$dbh->do("DELETE FROM products WHERE id = ?",
|
||||||
undef, $product_id);
|
undef, $product->id);
|
||||||
|
|
||||||
$dbh->bz_unlock_tables();
|
$dbh->bz_unlock_tables();
|
||||||
|
|
||||||
|
@ -583,73 +423,27 @@ if ($action eq 'delete') {
|
||||||
# (next action would be 'update')
|
# (next action would be 'update')
|
||||||
#
|
#
|
||||||
|
|
||||||
if ($action eq 'edit' || (!$action && $product)) {
|
if ($action eq 'edit' || (!$action && $product_name)) {
|
||||||
CheckProduct($product);
|
|
||||||
trick_taint($product);
|
my $product = Bugzilla::Product::check_product($product_name);
|
||||||
my $product_id = get_product_id($product);
|
|
||||||
my $classification_id=1;
|
|
||||||
if (Param('useclassification')) {
|
if (Param('useclassification')) {
|
||||||
# If a product has been given with no classification associated
|
my $classification;
|
||||||
# with it, take this information from the DB
|
if (!$classification_name) {
|
||||||
if ($classification) {
|
$classification =
|
||||||
CheckClassificationProduct($classification, $product);
|
new Bugzilla::Classification($product->classification_id);
|
||||||
} else {
|
} else {
|
||||||
$classification =
|
$classification =
|
||||||
$dbh->selectrow_array("SELECT classifications.name
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
FROM products, classifications
|
if ($classification->id != $product->classification_id) {
|
||||||
WHERE products.name = ?
|
ThrowUserError('classification_doesnt_exist_for_product',
|
||||||
AND classifications.id = products.classification_id",
|
{ product => $product->name,
|
||||||
undef, $product);
|
classification => $classification->name });
|
||||||
}
|
}
|
||||||
$classification_id = get_classification_id($classification);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$vars->{'classification'} = $classification;
|
$vars->{'classification'} = $classification;
|
||||||
|
|
||||||
# get data of product
|
|
||||||
$vars->{'product'} = $dbh->selectrow_hashref(qq{
|
|
||||||
SELECT id, name, classification_id, description,
|
|
||||||
milestoneurl, disallownew, votesperuser,
|
|
||||||
maxvotesperbug, votestoconfirm, defaultmilestone
|
|
||||||
FROM products
|
|
||||||
WHERE id = ?}, undef, $product_id);
|
|
||||||
|
|
||||||
|
|
||||||
$vars->{'components'} = $dbh->selectall_arrayref(qq{
|
|
||||||
SELECT name, description
|
|
||||||
FROM components
|
|
||||||
WHERE product_id = ?
|
|
||||||
ORDER BY name}, {'Slice' => {}},$product_id);
|
|
||||||
|
|
||||||
|
|
||||||
$vars->{'versions'} = $dbh->selectcol_arrayref(q{
|
|
||||||
SELECT value FROM versions
|
|
||||||
WHERE product_id = ?
|
|
||||||
ORDER BY value}, undef, $product_id);
|
|
||||||
|
|
||||||
if (Param('usetargetmilestone')) {
|
|
||||||
$vars->{'milestones'} = $dbh->selectcol_arrayref(q{
|
|
||||||
SELECT value
|
|
||||||
FROM milestones
|
|
||||||
WHERE product_id = ?
|
|
||||||
ORDER BY sortkey, value},
|
|
||||||
undef, $product_id);
|
|
||||||
}
|
}
|
||||||
|
my $group_controls = $product->group_controls;
|
||||||
my $query = qq{SELECT
|
|
||||||
groups.id, groups.name, groups.isactive,
|
|
||||||
group_control_map.entry,
|
|
||||||
group_control_map.membercontrol,
|
|
||||||
group_control_map.othercontrol,
|
|
||||||
group_control_map.canedit
|
|
||||||
FROM groups
|
|
||||||
INNER JOIN group_control_map
|
|
||||||
ON groups.id = group_control_map.group_id
|
|
||||||
WHERE group_control_map.product_id = ?
|
|
||||||
AND groups.isbuggroup != 0
|
|
||||||
ORDER BY groups.name};
|
|
||||||
my $groups = $dbh->selectall_arrayref($query, {'Slice' => {}},
|
|
||||||
$product_id);
|
|
||||||
|
|
||||||
# Convert Group Controls(membercontrol and othercontrol) from
|
# Convert Group Controls(membercontrol and othercontrol) from
|
||||||
# integer to string to display Membercontrol/Othercontrol names
|
# integer to string to display Membercontrol/Othercontrol names
|
||||||
|
@ -660,18 +454,15 @@ if ($action eq 'edit' || (!$action && $product)) {
|
||||||
(CONTROLMAPDEFAULT) => 'Default',
|
(CONTROLMAPDEFAULT) => 'Default',
|
||||||
(CONTROLMAPMANDATORY) => 'Mandatory'};
|
(CONTROLMAPMANDATORY) => 'Mandatory'};
|
||||||
|
|
||||||
foreach my $group (@$groups) {
|
foreach my $group (keys(%$group_controls)) {
|
||||||
$group->{'membercontrol'} =
|
foreach my $control ('membercontrol', 'othercontrol') {
|
||||||
$constants->{$group->{'membercontrol'}};
|
$group_controls->{$group}->{$control} =
|
||||||
$group->{'othercontrol'} =
|
$constants->{$group_controls->{$group}->{$control}};
|
||||||
$constants->{$group->{'othercontrol'}};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
$vars->{'group_controls'} = $group_controls;
|
||||||
|
|
||||||
$vars->{'groups'} = $groups;
|
$vars->{'product'} = $product;
|
||||||
|
|
||||||
$vars->{'bug_count'} = $dbh->selectrow_array(qq{
|
|
||||||
SELECT COUNT(*) FROM bugs
|
|
||||||
WHERE product_id = ?}, undef, $product_id);
|
|
||||||
|
|
||||||
$template->process("admin/products/edit.html.tmpl", $vars)
|
$template->process("admin/products/edit.html.tmpl", $vars)
|
||||||
|| ThrowTemplateError($template->error());
|
|| ThrowTemplateError($template->error());
|
||||||
|
@ -684,7 +475,8 @@ if ($action eq 'edit' || (!$action && $product)) {
|
||||||
#
|
#
|
||||||
|
|
||||||
if ($action eq 'updategroupcontrols') {
|
if ($action eq 'updategroupcontrols') {
|
||||||
my $product_id = get_product_id($product);
|
|
||||||
|
my $product = Bugzilla::Product::check_product($product_name);
|
||||||
my @now_na = ();
|
my @now_na = ();
|
||||||
my @now_mandatory = ();
|
my @now_mandatory = ();
|
||||||
foreach my $f ($cgi->param()) {
|
foreach my $f ($cgi->param()) {
|
||||||
|
@ -705,7 +497,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
WHERE groups.id IN(" . join(', ', @now_na) . ")
|
WHERE groups.id IN(" . join(', ', @now_na) . ")
|
||||||
AND bug_group_map.group_id = groups.id
|
AND bug_group_map.group_id = groups.id
|
||||||
AND bug_group_map.bug_id = bugs.bug_id
|
AND bug_group_map.bug_id = bugs.bug_id
|
||||||
AND bugs.product_id = $product_id " .
|
AND bugs.product_id = " . $product->id . " " .
|
||||||
$dbh->sql_group_by('groups.name'));
|
$dbh->sql_group_by('groups.name'));
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
my ($groupname, $bugcount) = FetchSQLData();
|
my ($groupname, $bugcount) = FetchSQLData();
|
||||||
|
@ -725,7 +517,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
INNER JOIN groups
|
INNER JOIN groups
|
||||||
ON bug_group_map.group_id = groups.id
|
ON bug_group_map.group_id = groups.id
|
||||||
WHERE groups.id IN(" . join(', ', @now_mandatory) . ")
|
WHERE groups.id IN(" . join(', ', @now_mandatory) . ")
|
||||||
AND bugs.product_id = $product_id
|
AND bugs.product_id = " . $product->id . "
|
||||||
AND bug_group_map.bug_id IS NULL " .
|
AND bug_group_map.bug_id IS NULL " .
|
||||||
$dbh->sql_group_by('groups.name'));
|
$dbh->sql_group_by('groups.name'));
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
|
@ -775,8 +567,8 @@ if ($action eq 'updategroupcontrols') {
|
||||||
SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit " .
|
SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit " .
|
||||||
"FROM groups " .
|
"FROM groups " .
|
||||||
"LEFT JOIN group_control_map " .
|
"LEFT JOIN group_control_map " .
|
||||||
"ON group_control_map.group_id = id AND product_id = $product_id " .
|
"ON group_control_map.group_id = id AND product_id = " .
|
||||||
"WHERE isbuggroup != 0 AND isactive != 0");
|
$product->id . " WHERE isbuggroup != 0 AND isactive != 0");
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
my ($groupid, $groupname, $entry, $membercontrol,
|
my ($groupid, $groupname, $entry, $membercontrol,
|
||||||
$othercontrol, $canedit) = FetchSQLData();
|
$othercontrol, $canedit) = FetchSQLData();
|
||||||
|
@ -800,7 +592,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
"(group_id, product_id, entry, " .
|
"(group_id, product_id, entry, " .
|
||||||
"membercontrol, othercontrol, canedit) " .
|
"membercontrol, othercontrol, canedit) " .
|
||||||
"VALUES " .
|
"VALUES " .
|
||||||
"($groupid, $product_id, $newentry, " .
|
"($groupid, " . $product->id . ", $newentry, " .
|
||||||
"$newmembercontrol, $newothercontrol, $newcanedit)");
|
"$newmembercontrol, $newothercontrol, $newcanedit)");
|
||||||
PopGlobalSQLState();
|
PopGlobalSQLState();
|
||||||
} elsif (($newentry != $entry)
|
} elsif (($newentry != $entry)
|
||||||
|
@ -814,7 +606,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
"othercontrol = $newothercontrol, " .
|
"othercontrol = $newothercontrol, " .
|
||||||
"canedit = $newcanedit " .
|
"canedit = $newcanedit " .
|
||||||
"WHERE group_id = $groupid " .
|
"WHERE group_id = $groupid " .
|
||||||
"AND product_id = $product_id");
|
"AND product_id = " . $product->id);
|
||||||
PopGlobalSQLState();
|
PopGlobalSQLState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,7 +615,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
PushGlobalSQLState();
|
PushGlobalSQLState();
|
||||||
SendSQL("DELETE FROM group_control_map " .
|
SendSQL("DELETE FROM group_control_map " .
|
||||||
"WHERE group_id = $groupid " .
|
"WHERE group_id = $groupid " .
|
||||||
"AND product_id = $product_id");
|
"AND product_id = " . $product->id);
|
||||||
PopGlobalSQLState();
|
PopGlobalSQLState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -836,7 +628,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
FROM bugs, bug_group_map
|
FROM bugs, bug_group_map
|
||||||
WHERE group_id = $groupid
|
WHERE group_id = $groupid
|
||||||
AND bug_group_map.bug_id = bugs.bug_id
|
AND bug_group_map.bug_id = bugs.bug_id
|
||||||
AND bugs.product_id = $product_id
|
AND bugs.product_id = " . $product->id . "
|
||||||
ORDER BY bugs.bug_id");
|
ORDER BY bugs.bug_id");
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
my ($bugid, $mailiscurrent) = FetchSQLData();
|
my ($bugid, $mailiscurrent) = FetchSQLData();
|
||||||
|
@ -871,7 +663,7 @@ if ($action eq 'updategroupcontrols') {
|
||||||
LEFT JOIN bug_group_map
|
LEFT JOIN bug_group_map
|
||||||
ON bug_group_map.bug_id = bugs.bug_id
|
ON bug_group_map.bug_id = bugs.bug_id
|
||||||
AND group_id = $groupid
|
AND group_id = $groupid
|
||||||
WHERE bugs.product_id = $product_id
|
WHERE bugs.product_id = " . $product->id . "
|
||||||
AND bug_group_map.bug_id IS NULL
|
AND bug_group_map.bug_id IS NULL
|
||||||
ORDER BY bugs.bug_id");
|
ORDER BY bugs.bug_id");
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
|
@ -903,8 +695,6 @@ if ($action eq 'updategroupcontrols') {
|
||||||
|
|
||||||
$vars->{'added_mandatory'} = \@added_mandatory;
|
$vars->{'added_mandatory'} = \@added_mandatory;
|
||||||
|
|
||||||
$vars->{'classification'} = $classification;
|
|
||||||
|
|
||||||
$vars->{'product'} = $product;
|
$vars->{'product'} = $product;
|
||||||
|
|
||||||
$template->process("admin/products/groupcontrol/updated.html.tmpl", $vars)
|
$template->process("admin/products/groupcontrol/updated.html.tmpl", $vars)
|
||||||
|
@ -917,28 +707,45 @@ if ($action eq 'updategroupcontrols') {
|
||||||
#
|
#
|
||||||
if ($action eq 'update') {
|
if ($action eq 'update') {
|
||||||
|
|
||||||
$vars->{'classification'} = $classification;
|
my $product_old_name = trim($cgi->param('product_old_name') || '');
|
||||||
|
|
||||||
my $productold = trim($cgi->param('productold') || '');
|
|
||||||
my $description = trim($cgi->param('description') || '');
|
my $description = trim($cgi->param('description') || '');
|
||||||
my $descriptionold = trim($cgi->param('descriptionold') || '');
|
|
||||||
my $disallownew = trim($cgi->param('disallownew') || '');
|
my $disallownew = trim($cgi->param('disallownew') || '');
|
||||||
my $disallownewold = trim($cgi->param('disallownewold') || '');
|
|
||||||
my $milestoneurl = trim($cgi->param('milestoneurl') || '');
|
my $milestoneurl = trim($cgi->param('milestoneurl') || '');
|
||||||
my $milestoneurlold = trim($cgi->param('milestoneurlold') || '');
|
|
||||||
my $votesperuser = trim($cgi->param('votesperuser') || 0);
|
my $votesperuser = trim($cgi->param('votesperuser') || 0);
|
||||||
my $votesperuserold = trim($cgi->param('votesperuserold') || 0);
|
|
||||||
my $maxvotesperbug = trim($cgi->param('maxvotesperbug') || 0);
|
my $maxvotesperbug = trim($cgi->param('maxvotesperbug') || 0);
|
||||||
my $maxvotesperbugold = trim($cgi->param('maxvotesperbugold') || 0);
|
|
||||||
my $votestoconfirm = trim($cgi->param('votestoconfirm') || 0);
|
my $votestoconfirm = trim($cgi->param('votestoconfirm') || 0);
|
||||||
my $votestoconfirmold = trim($cgi->param('votestoconfirmold') || 0);
|
|
||||||
my $defaultmilestone = trim($cgi->param('defaultmilestone') || '---');
|
my $defaultmilestone = trim($cgi->param('defaultmilestone') || '---');
|
||||||
my $defaultmilestoneold = trim($cgi->param('defaultmilestoneold') || '---');
|
|
||||||
|
|
||||||
my $checkvotes = 0;
|
my $checkvotes = 0;
|
||||||
|
|
||||||
CheckProduct($productold);
|
my $product_old = Bugzilla::Product::check_product($product_old_name);
|
||||||
my $product_id = get_product_id($productold);
|
|
||||||
|
if (Param('useclassification')) {
|
||||||
|
my $classification;
|
||||||
|
if (!$classification_name) {
|
||||||
|
$classification =
|
||||||
|
new Bugzilla::Classification($product_old->classification_id);
|
||||||
|
} else {
|
||||||
|
$classification =
|
||||||
|
Bugzilla::Classification::check_classification($classification_name);
|
||||||
|
if ($classification->id != $product_old->classification_id) {
|
||||||
|
ThrowUserError('classification_doesnt_exist_for_product',
|
||||||
|
{ product => $product_old->name,
|
||||||
|
classification => $classification->name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$vars->{'classification'} = $classification;
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ($product_name) {
|
||||||
|
ThrowUserError('prod_cant_delete_name',
|
||||||
|
{product => $product_old->name});
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ($description) {
|
||||||
|
ThrowUserError('prod_cant_delete_description',
|
||||||
|
{product => $product_old->name});
|
||||||
|
}
|
||||||
|
|
||||||
my $stored_maxvotesperbug = $maxvotesperbug;
|
my $stored_maxvotesperbug = $maxvotesperbug;
|
||||||
if (!detaint_natural($maxvotesperbug)) {
|
if (!detaint_natural($maxvotesperbug)) {
|
||||||
|
@ -958,9 +765,6 @@ if ($action eq 'update') {
|
||||||
{votestoconfirm => $stored_votestoconfirm});
|
{votestoconfirm => $stored_votestoconfirm});
|
||||||
}
|
}
|
||||||
|
|
||||||
# Note that we got the $product_id using $productold above so it will
|
|
||||||
# remain static even after we rename the product in the database.
|
|
||||||
|
|
||||||
$dbh->bz_lock_tables('products WRITE',
|
$dbh->bz_lock_tables('products WRITE',
|
||||||
'versions READ',
|
'versions READ',
|
||||||
'groups WRITE',
|
'groups WRITE',
|
||||||
|
@ -968,120 +772,87 @@ if ($action eq 'update') {
|
||||||
'profiles WRITE',
|
'profiles WRITE',
|
||||||
'milestones READ');
|
'milestones READ');
|
||||||
|
|
||||||
if ($disallownew ne $disallownewold) {
|
my $testproduct =
|
||||||
$disallownew = $disallownew ? 1 : 0;
|
new Bugzilla::Product({name => $product_name});
|
||||||
SendSQL("UPDATE products
|
if (lc($product_name) ne lc($product_old->name) &&
|
||||||
SET disallownew=$disallownew
|
$testproduct) {
|
||||||
WHERE id=$product_id");
|
ThrowUserError('prod_name_already_in_use',
|
||||||
$vars->{'updated_bugsubmitstatus'} = 1;
|
{product => $product_name});
|
||||||
$vars->{'new_bugsubmitstatus'} = $disallownew;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($description ne $descriptionold) {
|
my $milestone = new Bugzilla::Milestone($product_old->id,
|
||||||
unless ($description) {
|
$defaultmilestone);
|
||||||
ThrowUserError('prod_cant_delete_description',
|
if (!$milestone) {
|
||||||
{product => $productold});
|
ThrowUserError('prod_must_define_defaultmilestone',
|
||||||
|
{product => $product_old->name,
|
||||||
|
defaultmilestone => $defaultmilestone,
|
||||||
|
classification => $classification_name});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$disallownew = $disallownew ? 1 : 0;
|
||||||
|
if ($disallownew ne $product_old->disallow_new) {
|
||||||
|
SendSQL("UPDATE products
|
||||||
|
SET disallownew=$disallownew
|
||||||
|
WHERE id = " . $product_old->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($description ne $product_old->description) {
|
||||||
SendSQL("UPDATE products
|
SendSQL("UPDATE products
|
||||||
SET description=" . SqlQuote($description) . "
|
SET description=" . SqlQuote($description) . "
|
||||||
WHERE id=$product_id");
|
WHERE id = " . $product_old->id);
|
||||||
$vars->{'updated_description'} = 1;
|
|
||||||
$vars->{'old_description'} = $descriptionold;
|
|
||||||
$vars->{'new_description'} = $description;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Param('usetargetmilestone')
|
if (Param('usetargetmilestone')
|
||||||
&& ($milestoneurl ne $milestoneurlold)) {
|
&& ($milestoneurl ne $product_old->milestone_url)) {
|
||||||
SendSQL("UPDATE products
|
SendSQL("UPDATE products
|
||||||
SET milestoneurl=" . SqlQuote($milestoneurl) . "
|
SET milestoneurl=" . SqlQuote($milestoneurl) . "
|
||||||
WHERE id=$product_id");
|
WHERE id = " . $product_old->id);
|
||||||
$vars->{'updated_milestoneurl'} = 1;
|
|
||||||
$vars->{'old_milestoneurl'} = $milestoneurlold;
|
|
||||||
$vars->{'new_milestoneurl'} = $milestoneurl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($votesperuser ne $votesperuserold) {
|
if ($votesperuser ne $product_old->votes_per_user) {
|
||||||
SendSQL("UPDATE products
|
SendSQL("UPDATE products
|
||||||
SET votesperuser=$votesperuser
|
SET votesperuser=$votesperuser
|
||||||
WHERE id=$product_id");
|
WHERE id = " . $product_old->id);
|
||||||
$vars->{'updated_votesperuser'} = 1;
|
|
||||||
$vars->{'old_votesperuser'} = $votesperuserold;
|
|
||||||
$vars->{'new_votesperuser'} = $votesperuser;
|
|
||||||
|
|
||||||
$checkvotes = 1;
|
$checkvotes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($maxvotesperbug ne $maxvotesperbugold) {
|
if ($maxvotesperbug ne $product_old->max_votes_per_bug) {
|
||||||
SendSQL("UPDATE products
|
SendSQL("UPDATE products
|
||||||
SET maxvotesperbug=$maxvotesperbug
|
SET maxvotesperbug=$maxvotesperbug
|
||||||
WHERE id=$product_id");
|
WHERE id = " . $product_old->id);
|
||||||
$vars->{'updated_maxvotesperbug'} = 1;
|
|
||||||
$vars->{'old_maxvotesperbug'} = $maxvotesperbugold;
|
|
||||||
$vars->{'new_maxvotesperbug'} = $maxvotesperbug;
|
|
||||||
|
|
||||||
$checkvotes = 1;
|
$checkvotes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($votestoconfirm ne $votestoconfirmold) {
|
if ($votestoconfirm ne $product_old->votes_to_confirm) {
|
||||||
SendSQL("UPDATE products
|
SendSQL("UPDATE products
|
||||||
SET votestoconfirm=$votestoconfirm
|
SET votestoconfirm=$votestoconfirm
|
||||||
WHERE id=$product_id");
|
WHERE id = " . $product_old->id);
|
||||||
|
|
||||||
$vars->{'updated_votestoconfirm'} = 1;
|
|
||||||
$vars->{'old_votestoconfirm'} = $votestoconfirmold;
|
|
||||||
$vars->{'new_votestoconfirm'} = $votestoconfirm;
|
|
||||||
|
|
||||||
$checkvotes = 1;
|
$checkvotes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($defaultmilestone ne $defaultmilestoneold) {
|
if ($defaultmilestone ne $product_old->default_milestone) {
|
||||||
SendSQL("SELECT value FROM milestones " .
|
|
||||||
"WHERE value = " . SqlQuote($defaultmilestone) .
|
|
||||||
" AND product_id = $product_id");
|
|
||||||
if (!FetchOneColumn()) {
|
|
||||||
ThrowUserError('prod_must_define_defaultmilestone',
|
|
||||||
{product => $productold,
|
|
||||||
defaultmilestone => $defaultmilestone,
|
|
||||||
classification => $classification});
|
|
||||||
}
|
|
||||||
SendSQL("UPDATE products " .
|
SendSQL("UPDATE products " .
|
||||||
"SET defaultmilestone = " . SqlQuote($defaultmilestone) .
|
"SET defaultmilestone = " . SqlQuote($defaultmilestone) .
|
||||||
"WHERE id=$product_id");
|
"WHERE id = " . $product_old->id);
|
||||||
|
|
||||||
$vars->{'updated_defaultmilestone'} = 1;
|
|
||||||
$vars->{'old_defaultmilestone'} = $defaultmilestoneold;
|
|
||||||
$vars->{'new_defaultmilestone'} = $defaultmilestone;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $qp = SqlQuote($product);
|
my $qp = SqlQuote($product_name);
|
||||||
my $qpold = SqlQuote($productold);
|
|
||||||
|
|
||||||
if ($product ne $productold) {
|
if ($product_name ne $product_old->name) {
|
||||||
unless ($product) {
|
SendSQL("UPDATE products SET name=$qp WHERE id= ".$product_old->id);
|
||||||
ThrowUserError('prod_cant_delete_name',
|
|
||||||
{product => $productold});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lc($product) ne lc($productold) &&
|
|
||||||
TestProduct($product)) {
|
|
||||||
ThrowUserError('prod_name_already_in_use',
|
|
||||||
{product => $product});
|
|
||||||
}
|
|
||||||
|
|
||||||
SendSQL("UPDATE products SET name=$qp WHERE id=$product_id");
|
|
||||||
|
|
||||||
$vars->{'updated_product'} = 1;
|
|
||||||
$vars->{'old_product'} = $productold;
|
|
||||||
$vars->{'new_product'} = $product;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
$dbh->bz_unlock_tables();
|
$dbh->bz_unlock_tables();
|
||||||
unlink "$datadir/versioncache";
|
unlink "$datadir/versioncache";
|
||||||
|
|
||||||
|
my $product = new Bugzilla::Product({name => $product_name});
|
||||||
|
|
||||||
if ($checkvotes) {
|
if ($checkvotes) {
|
||||||
$vars->{'checkvotes'} = 1;
|
$vars->{'checkvotes'} = 1;
|
||||||
|
|
||||||
|
@ -1092,7 +863,7 @@ if ($action eq 'update') {
|
||||||
SendSQL("SELECT votes.who, votes.bug_id " .
|
SendSQL("SELECT votes.who, votes.bug_id " .
|
||||||
"FROM votes, bugs " .
|
"FROM votes, bugs " .
|
||||||
"WHERE bugs.bug_id = votes.bug_id " .
|
"WHERE bugs.bug_id = votes.bug_id " .
|
||||||
" AND bugs.product_id = $product_id " .
|
" AND bugs.product_id = " . $product->id .
|
||||||
" AND votes.vote_count > $maxvotesperbug");
|
" AND votes.vote_count > $maxvotesperbug");
|
||||||
my @list;
|
my @list;
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
|
@ -1122,7 +893,7 @@ if ($action eq 'update') {
|
||||||
|
|
||||||
SendSQL("SELECT votes.who, votes.vote_count FROM votes, bugs " .
|
SendSQL("SELECT votes.who, votes.vote_count FROM votes, bugs " .
|
||||||
"WHERE bugs.bug_id = votes.bug_id " .
|
"WHERE bugs.bug_id = votes.bug_id " .
|
||||||
" AND bugs.product_id = $product_id");
|
" AND bugs.product_id = " . $product->id);
|
||||||
my %counts;
|
my %counts;
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
my ($who, $count) = (FetchSQLData());
|
my ($who, $count) = (FetchSQLData());
|
||||||
|
@ -1137,7 +908,7 @@ if ($action eq 'update') {
|
||||||
if ($counts{$who} > $votesperuser) {
|
if ($counts{$who} > $votesperuser) {
|
||||||
SendSQL("SELECT votes.bug_id FROM votes, bugs " .
|
SendSQL("SELECT votes.bug_id FROM votes, bugs " .
|
||||||
"WHERE bugs.bug_id = votes.bug_id " .
|
"WHERE bugs.bug_id = votes.bug_id " .
|
||||||
" AND bugs.product_id = $product_id " .
|
" AND bugs.product_id = " . $product->id .
|
||||||
" AND votes.who = $who");
|
" AND votes.who = $who");
|
||||||
while (MoreSQLData()) {
|
while (MoreSQLData()) {
|
||||||
my ($id) = FetchSQLData();
|
my ($id) = FetchSQLData();
|
||||||
|
@ -1157,7 +928,7 @@ if ($action eq 'update') {
|
||||||
WHERE product_id = ?
|
WHERE product_id = ?
|
||||||
AND bug_status = 'UNCONFIRMED'
|
AND bug_status = 'UNCONFIRMED'
|
||||||
AND votes >= ?",
|
AND votes >= ?",
|
||||||
undef, ($product_id, $votestoconfirm));
|
undef, ($product->id, $votestoconfirm));
|
||||||
|
|
||||||
my @updated_bugs = ();
|
my @updated_bugs = ();
|
||||||
foreach my $bug_id (@$bug_list) {
|
foreach my $bug_id (@$bug_list) {
|
||||||
|
@ -1170,7 +941,9 @@ if ($action eq 'update') {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$vars->{'name'} = $product;
|
$vars->{'old_product'} = $product_old;
|
||||||
|
$vars->{'product'} = $product;
|
||||||
|
|
||||||
$template->process("admin/products/updated.html.tmpl", $vars)
|
$template->process("admin/products/updated.html.tmpl", $vars)
|
||||||
|| ThrowTemplateError($template->error());
|
|| ThrowTemplateError($template->error());
|
||||||
|
|
||||||
|
@ -1182,21 +955,19 @@ if ($action eq 'update') {
|
||||||
#
|
#
|
||||||
|
|
||||||
if ($action eq 'editgroupcontrols') {
|
if ($action eq 'editgroupcontrols') {
|
||||||
my $product_id = get_product_id($product);
|
my $product = Bugzilla::Product::check_product($product_name);
|
||||||
$product_id
|
|
||||||
|| ThrowUserError("invalid_product_name", { product => $product });
|
|
||||||
# Display a group if it is either enabled or has bugs for this product.
|
# Display a group if it is either enabled or has bugs for this product.
|
||||||
SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit, " .
|
SendSQL("SELECT id, name, entry, membercontrol, othercontrol, canedit, " .
|
||||||
"isactive, COUNT(bugs.bug_id) " .
|
"isactive, COUNT(bugs.bug_id) " .
|
||||||
"FROM groups " .
|
"FROM groups " .
|
||||||
"LEFT JOIN group_control_map " .
|
"LEFT JOIN group_control_map " .
|
||||||
"ON group_control_map.group_id = id " .
|
"ON group_control_map.group_id = id " .
|
||||||
"AND group_control_map.product_id = $product_id " .
|
"AND group_control_map.product_id = " . $product->id .
|
||||||
" LEFT JOIN bug_group_map " .
|
" LEFT JOIN bug_group_map " .
|
||||||
"ON bug_group_map.group_id = groups.id " .
|
"ON bug_group_map.group_id = groups.id " .
|
||||||
"LEFT JOIN bugs " .
|
"LEFT JOIN bugs " .
|
||||||
"ON bugs.bug_id = bug_group_map.bug_id " .
|
"ON bugs.bug_id = bug_group_map.bug_id " .
|
||||||
"AND bugs.product_id = $product_id " .
|
"AND bugs.product_id = " . $product->id .
|
||||||
" WHERE isbuggroup != 0 " .
|
" WHERE isbuggroup != 0 " .
|
||||||
"AND (isactive != 0 OR entry IS NOT NULL " .
|
"AND (isactive != 0 OR entry IS NOT NULL " .
|
||||||
"OR bugs.bug_id IS NOT NULL) " .
|
"OR bugs.bug_id IS NOT NULL) " .
|
||||||
|
@ -1218,8 +989,9 @@ if ($action eq 'editgroupcontrols') {
|
||||||
push @groups,\%group;
|
push @groups,\%group;
|
||||||
}
|
}
|
||||||
$vars->{'product'} = $product;
|
$vars->{'product'} = $product;
|
||||||
$vars->{'classification'} = $classification;
|
|
||||||
$vars->{'groups'} = \@groups;
|
$vars->{'groups'} = \@groups;
|
||||||
|
|
||||||
$vars->{'const'} = {
|
$vars->{'const'} = {
|
||||||
'CONTROLMAPNA' => CONTROLMAPNA,
|
'CONTROLMAPNA' => CONTROLMAPNA,
|
||||||
'CONTROLMAPSHOWN' => CONTROLMAPSHOWN,
|
'CONTROLMAPSHOWN' => CONTROLMAPSHOWN,
|
||||||
|
|
|
@ -15,32 +15,16 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# product_name: string; The name of the product
|
# product: Bugzilla::Product object; The product
|
||||||
#
|
|
||||||
# prod_description: string; Product description, may be empty
|
|
||||||
#
|
#
|
||||||
# (classification fields available if Param('useclassification') is enabled:)
|
# (classification fields available if Param('useclassification') is enabled:)
|
||||||
#
|
#
|
||||||
# classification: string; The name of the classification the product is in
|
# classification: Bugzilla::Classification object; The classification
|
||||||
#
|
# the product is in
|
||||||
# class_description: string; Classification description, may be empty
|
|
||||||
#
|
|
||||||
# bug_count: number; The number of bugs belonging to the product
|
|
||||||
#
|
|
||||||
# milestoneurl: string; milestone url, if milestones are in use,
|
|
||||||
# may be empty
|
|
||||||
#
|
|
||||||
# disallownew: boolean; Are new bugs allowed for the product flag
|
|
||||||
#
|
|
||||||
# components: list of hashes, members are: name, description
|
|
||||||
#
|
|
||||||
# versions: list of version values.
|
|
||||||
#
|
|
||||||
# milestones: list of milestone values.
|
|
||||||
#
|
#
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% title = BLOCK %]Delete Product '[% product_name FILTER html %]'
|
[% title = BLOCK %]Delete Product '[% product.name FILTER html %]'
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% PROCESS global/header.html.tmpl
|
[% PROCESS global/header.html.tmpl
|
||||||
|
@ -50,25 +34,12 @@
|
||||||
|
|
||||||
[% IF classification %]
|
[% IF classification %]
|
||||||
[% classification_url_part = BLOCK %]&classification=
|
[% classification_url_part = BLOCK %]&classification=
|
||||||
[%- classification FILTER url_quote %]
|
[%- classification.name FILTER url_quote %]
|
||||||
[%- END %]
|
[%- END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
[% classification_url_part = "" %]
|
[% classification_url_part = "" %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% UNLESS class_description %]
|
|
||||||
[% class_description = '<span style="color: red">missing</span>' %]
|
|
||||||
[% END %]
|
|
||||||
[% UNLESS prod_description %]
|
|
||||||
[% prod_description = '<span style="color: red">missing</span>' %]
|
|
||||||
[% END %]
|
|
||||||
|
|
||||||
[% IF disallownew %]
|
|
||||||
[% disallownew = "closed" %]
|
|
||||||
[% ELSE %]
|
|
||||||
[% disallownew = "open" %]
|
|
||||||
[% END %]
|
|
||||||
|
|
||||||
<table border="1" cellpadding="4" cellspacing="0">
|
<table border="1" cellpadding="4" cellspacing="0">
|
||||||
<tr bgcolor="#6666FF">
|
<tr bgcolor="#6666FF">
|
||||||
<th valign="top" align="left">Field</th>
|
<th valign="top" align="left">Field</th>
|
||||||
|
@ -78,37 +49,49 @@
|
||||||
[% IF Param('useclassification') %]
|
[% IF Param('useclassification') %]
|
||||||
<tr>
|
<tr>
|
||||||
<td>Classification:</td>
|
<td>Classification:</td>
|
||||||
<td>[% classification FILTER html %]</td>
|
<td>[% classification.name FILTER html %]</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Classification Description:</td>
|
<td>Classification Description:</td>
|
||||||
[%# descriptions are intentionally not filtered to allow html content %]
|
[%# descriptions are intentionally not filtered to allow html content %]
|
||||||
<td>[% class_description FILTER none %]</td>
|
<td>
|
||||||
|
[% IF classification.description %]
|
||||||
|
[% classification.description FILTER none %]
|
||||||
|
[% ELSE %]
|
||||||
|
<span style="color: red">missing</span>
|
||||||
|
[% END %]
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">Product:</td>
|
<td valign="top">Product:</td>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
<a href="editproducts.cgi?product=[% product_name FILTER url_quote %]
|
<a href="editproducts.cgi?product=[% product.name FILTER url_quote %]
|
||||||
[%- classification_url_part %]">
|
[%- classification_url_part %]">
|
||||||
[% product_name FILTER html %]
|
[% product.name FILTER html %]
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">Description:</td>
|
<td valign="top">Description:</td>
|
||||||
[%# descriptions are intentionally not filtered to allow html content %]
|
[%# descriptions are intentionally not filtered to allow html content %]
|
||||||
<td valign="top">[% prod_description FILTER none %]</td>
|
<td valign="top">
|
||||||
|
[% IF product.description %]
|
||||||
|
[% product.description FILTER none %]
|
||||||
|
[% ELSE %]
|
||||||
|
<span style="color: red">missing</span>
|
||||||
|
[% END %]
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
[% IF Param('usetargetmilestone') %]
|
[% IF Param('usetargetmilestone') %]
|
||||||
<tr>
|
<tr>
|
||||||
<td>Milestone URL:</td>
|
<td>Milestone URL:</td>
|
||||||
<td>
|
<td>
|
||||||
[% IF milestoneurl %]
|
[% IF product.milestone_url %]
|
||||||
<a href="[% milestoneurl FILTER uri %]">
|
<a href="[% product.milestone_url FILTER uri %]">
|
||||||
[%- milestoneurl FILTER html %]
|
[%- product.milestone_url FILTER html %]
|
||||||
</a>
|
</a>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
none
|
none
|
||||||
|
@ -119,15 +102,21 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>Closed for [% terms.bugs %]:</td>
|
<td>Closed for [% terms.bugs %]:</td>
|
||||||
<td>[% disallownew FILTER html %]</td>
|
<td>
|
||||||
|
[% IF product.disallownew %]
|
||||||
|
closed
|
||||||
|
[% ELSE %]
|
||||||
|
open
|
||||||
|
[% END %]
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
[% IF components.size > 0 %]
|
[% IF product.components.size > 0 %]
|
||||||
<a href="editcomponents.cgi?product=[% product_name FILTER url_quote %]
|
<a href="editcomponents.cgi?product=[% product.name FILTER url_quote %]
|
||||||
[%- classification_url_part %]"
|
[%- classification_url_part %]"
|
||||||
title="Edit components for product '[% product_name FILTER html %]'">
|
title="Edit components for product '[% product.name FILTER html %]'">
|
||||||
Components:
|
Components:
|
||||||
</a>
|
</a>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
|
@ -135,9 +124,9 @@
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
[% IF components.size > 0 %]
|
[% IF product.components.size > 0 %]
|
||||||
<table>
|
<table>
|
||||||
[% FOREACH c = components %]
|
[% FOREACH c = product.components %]
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right">[% c.name FILTER html %]:</th>
|
<th align="right">[% c.name FILTER html %]:</th>
|
||||||
[%# descriptions are intentionally not filtered to allow html content %]
|
[%# descriptions are intentionally not filtered to allow html content %]
|
||||||
|
@ -159,8 +148,8 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
[% IF versions.size > 0 %]
|
[% IF product.versions.size > 0 %]
|
||||||
<a href="editversions.cgi?product=[%- product_name FILTER url_quote %]
|
<a href="editversions.cgi?product=[%- product.name FILTER url_quote %]
|
||||||
[%- classification_url_part %]">
|
[%- classification_url_part %]">
|
||||||
Versions:
|
Versions:
|
||||||
</a>
|
</a>
|
||||||
|
@ -168,9 +157,9 @@
|
||||||
Versions:
|
Versions:
|
||||||
[% END %]
|
[% END %]
|
||||||
<td>
|
<td>
|
||||||
[% IF versions.size > 0 %]
|
[% IF product.versions.size > 0 %]
|
||||||
[% FOREACH v = versions %]
|
[% FOREACH v = product.versions %]
|
||||||
[% v FILTER html %]<br>
|
[% v.name FILTER html %]<br>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
none
|
none
|
||||||
|
@ -180,8 +169,8 @@
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td valign="top">
|
<td valign="top">
|
||||||
[% IF milestones.size > 0 %]
|
[% IF product.milestones.size > 0 %]
|
||||||
<a href="editmilestones.cgi?product=[%- product_name FILTER url_quote %]
|
<a href="editmilestones.cgi?product=[%- product.name FILTER url_quote %]
|
||||||
[%- classification_url_part -%]">
|
[%- classification_url_part -%]">
|
||||||
Milestones:
|
Milestones:
|
||||||
</a>
|
</a>
|
||||||
|
@ -190,9 +179,9 @@
|
||||||
[% END %]
|
[% END %]
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
[% IF milestones.size > 0 %]
|
[% IF product.milestones.size > 0 %]
|
||||||
[% FOREACH m = milestones %]
|
[% FOREACH m = product.milestones %]
|
||||||
[% m FILTER html %]<br>
|
[% m.name FILTER html %]<br>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
none
|
none
|
||||||
|
@ -203,12 +192,12 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>[% terms.Bugs %]:</td>
|
<td>[% terms.Bugs %]:</td>
|
||||||
<td>
|
<td>
|
||||||
[% IF bug_count %]
|
[% IF product.bug_count %]
|
||||||
<a href="buglist.cgi?product=[%- product_name FILTER url_quote %]
|
<a href="buglist.cgi?product=[%- product.name FILTER url_quote %]
|
||||||
[%- classification_url_part %]"
|
[%- classification_url_part %]"
|
||||||
title="List of [% terms.bugs %] for product '
|
title="List of [% terms.bugs %] for product '
|
||||||
[%- product_name FILTER html %]'">
|
[%- product.name FILTER html %]'">
|
||||||
[% bug_count %]
|
[% product.bug_count FILTER html %]
|
||||||
</a>
|
</a>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
none
|
none
|
||||||
|
@ -219,21 +208,21 @@
|
||||||
|
|
||||||
<h2>Confirmation</h2>
|
<h2>Confirmation</h2>
|
||||||
|
|
||||||
[% IF bug_count %]
|
[% IF product.bug_count %]
|
||||||
|
|
||||||
[% IF !Param("allowbugdeletion") %]
|
[% IF !Param("allowbugdeletion") %]
|
||||||
|
|
||||||
Sorry, there
|
Sorry, there
|
||||||
|
|
||||||
[% IF bug_count > 1 %]
|
[% IF product.bug_count > 1 %]
|
||||||
are [% bug_count %] [%+ terms.bugs %]
|
are [% product.bug_count FILTER html %] [%+ terms.bugs %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
is 1 [% terms.bug %]
|
is 1 [% terms.bug %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
outstanding for this product. You must reassign
|
outstanding for this product. You must reassign
|
||||||
|
|
||||||
[% IF bug_count > 1 %]
|
[% IF product.bug_count > 1 %]
|
||||||
those [% terms.bugs %]
|
those [% terms.bugs %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
that [% terms.bug %]
|
that [% terms.bug %]
|
||||||
|
@ -247,8 +236,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
There
|
There
|
||||||
[% IF bug_count > 1 %]
|
[% IF product.bug_count > 1 %]
|
||||||
are [% bug_count %] [%+ terms.bugs %]
|
are [% product.bug_count FILTER html %] [%+ terms.bugs %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
is 1 [% terms.bug %]
|
is 1 [% terms.bug %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
@ -263,16 +252,16 @@
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF bug_count == 0 || Param('allowbugdeletion') %]
|
[% IF product.bug_count == 0 || Param('allowbugdeletion') %]
|
||||||
|
|
||||||
<p>Do you really want to delete this product?<p>
|
<p>Do you really want to delete this product?<p>
|
||||||
|
|
||||||
<form method="post" action="editproducts.cgi">
|
<form method="post" action="editproducts.cgi">
|
||||||
<input type="submit" value="Yes, delete">
|
<input type="submit" value="Yes, delete">
|
||||||
<input type="hidden" name="action" value="delete">
|
<input type="hidden" name="action" value="delete">
|
||||||
<input type="hidden" name="product" value="[% product_name FILTER html %]">
|
<input type="hidden" name="product" value="[% product.name FILTER html %]">
|
||||||
<input type="hidden" name="classification"
|
<input type="hidden" name="classification"
|
||||||
value="[% classification FILTER html %]">
|
value="[% classification.name FILTER html %]">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# classification: string; name of the classification in which the new
|
# classification: Bugzilla::Classification object; If classifications
|
||||||
# product is created.
|
# are enabled, then this is
|
||||||
|
# the currently selected classification
|
||||||
#
|
#
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
|
@ -56,9 +57,11 @@
|
||||||
<input type="hidden" name="open_name" value="All Open">
|
<input type="hidden" name="open_name" value="All Open">
|
||||||
<input type="hidden" name="action" value="new">
|
<input type="hidden" name="action" value="new">
|
||||||
<input type="hidden" name="classification"
|
<input type="hidden" name="classification"
|
||||||
value="[% classification FILTER html %]">
|
value="[% classification.name FILTER html %]">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
[% PROCESS "admin/products/footer.html.tmpl" no_add_product_link = 1 %]
|
[% PROCESS "admin/products/footer.html.tmpl"
|
||||||
|
no_add_product_link = 1
|
||||||
|
no_edit_product_link = 1 %]
|
||||||
|
|
||||||
[% PROCESS global/footer.html.tmpl %]
|
[% PROCESS global/footer.html.tmpl %]
|
||||||
|
|
|
@ -14,18 +14,23 @@
|
||||||
# Contributor(s): Gabriel S. Oliveira <gabriel@async.com.br>
|
# Contributor(s): Gabriel S. Oliveira <gabriel@async.com.br>
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
|
[%# INTERFACE:
|
||||||
|
# product: Bugzilla::Product object; the Product created.
|
||||||
|
#
|
||||||
|
#%]
|
||||||
|
|
||||||
[% PROCESS global/header.html.tmpl
|
[% PROCESS global/header.html.tmpl
|
||||||
title = 'New Product Created'
|
title = 'New Product Created'
|
||||||
%]
|
%]
|
||||||
<br>
|
<br>
|
||||||
<div style='border: 1px red solid; padding: 1ex;'>
|
<div style='border: 1px red solid; padding: 1ex;'>
|
||||||
<b>You will need to
|
<b>You will need to
|
||||||
<a href="editcomponents.cgi?action=add&product=[% product FILTER url_quote %]">
|
<a href="editcomponents.cgi?action=add&product=[% product.name FILTER url_quote %]">
|
||||||
add at least one component
|
add at least one component
|
||||||
</a> before you can enter [% terms.bugs %] against this product
|
</a> before you can enter [% terms.bugs %] against this product
|
||||||
</b>
|
</b>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[% PROCESS "admin/products/footer.html.tmpl" name = product %]
|
[% PROCESS "admin/products/footer.html.tmpl" %]
|
||||||
|
|
||||||
[% PROCESS global/footer.html.tmpl %]
|
[% PROCESS global/footer.html.tmpl %]
|
||||||
|
|
|
@ -15,11 +15,16 @@
|
||||||
#
|
#
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
|
[%# INTERFACE:
|
||||||
|
# product: Bugzilla::Product object; The product
|
||||||
|
#
|
||||||
|
#%]
|
||||||
|
|
||||||
[% PROCESS global/header.html.tmpl
|
[% PROCESS global/header.html.tmpl
|
||||||
title = 'Deleting product'
|
title = 'Deleting product'
|
||||||
%]
|
%]
|
||||||
|
|
||||||
[% IF nb_bugs %]
|
[% IF product.bug_count %]
|
||||||
All references to deleted [% terms.bugs %] removed.
|
All references to deleted [% terms.bugs %] removed.
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
@ -35,7 +40,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Product [% product FILTER html %] deleted.
|
Product [% product.name FILTER html %] deleted.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[% PROCESS admin/products/footer.html.tmpl
|
[% PROCESS admin/products/footer.html.tmpl
|
||||||
|
|
|
@ -17,14 +17,15 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# classification: string; name of classification product is in.
|
# product: Bugzilla::Product object; The product
|
||||||
# product: array; an array of product objects.
|
#
|
||||||
|
# classification: Bugzilla::Classifiation object; classification product is in.
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% IF Param('useclassification') %]
|
[% IF Param('useclassification') %]
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right"><b>Classification:</b></th>
|
<th align="right"><b>Classification:</b></th>
|
||||||
<td><b>[% classification FILTER html %]</b></td>
|
<td><b>[% classification.name FILTER html %]</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,14 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# classification: string; name of classification product is in.
|
# product: Bugzilla::Product object; The product
|
||||||
# product: an array of product objects.
|
#
|
||||||
# components: an array of component object(s) related to the product.
|
# (classification fields available if Param('useclassification') is enabled:)
|
||||||
# groups: an array of group objects related to the product.
|
#
|
||||||
# versions: an array of version objects related to product.
|
# classification: Bugzilla::Classification object; The classification
|
||||||
# milestones: an array of milestones objects related to product.
|
# the product is in
|
||||||
# bug_count: integer; number of bugs in this product.
|
#
|
||||||
|
# groups_controls: a hash of group controls related to the product.
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% title = BLOCK %]Edit Product[% END %]
|
[% title = BLOCK %]Edit Product[% END %]
|
||||||
|
@ -44,8 +45,8 @@
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
[% IF components.size -%]
|
[% IF product.components.size -%]
|
||||||
[% FOREACH component = components %]
|
[% FOREACH component = product.components %]
|
||||||
<b>[% component.name FILTER html %]:</b>
|
<b>[% component.name FILTER html %]:</b>
|
||||||
[% IF component.description %]
|
[% IF component.description %]
|
||||||
[% component.description FILTER none %]
|
[% component.description FILTER none %]
|
||||||
|
@ -65,9 +66,9 @@
|
||||||
versions:</a>
|
versions:</a>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
[%- IF versions.size -%]
|
[%- IF product.versions.size -%]
|
||||||
[% FOREACH v = versions %]
|
[% FOREACH v = product.versions %]
|
||||||
[% v FILTER html %]
|
[% v.name FILTER html %]
|
||||||
<br>
|
<br>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
|
@ -82,9 +83,9 @@ versions:</a>
|
||||||
Edit milestones:</a>
|
Edit milestones:</a>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
[%- IF milestones.size -%]
|
[%- IF product.milestones.size -%]
|
||||||
[%- FOREACH m = milestones -%]
|
[%- FOREACH m = product.milestones -%]
|
||||||
[% m FILTER html %]
|
[% m.name FILTER html %]
|
||||||
<br>
|
<br>
|
||||||
[% END %]
|
[% END %]
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
|
@ -97,15 +98,15 @@ versions:</a>
|
||||||
<th align="right" valign="top">
|
<th align="right" valign="top">
|
||||||
<a href="editproducts.cgi?action=editgroupcontrols&product=
|
<a href="editproducts.cgi?action=editgroupcontrols&product=
|
||||||
[%- product.name FILTER url_quote %]&classification=
|
[%- product.name FILTER url_quote %]&classification=
|
||||||
[%- classification FILTER url_quote %]">
|
[%- classification.name FILTER url_quote %]">
|
||||||
Edit Group Access Controls:
|
Edit Group Access Controls:
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
[% IF groups.size %]
|
[% IF group_controls.size %]
|
||||||
[% FOREACH g = groups %]
|
[% FOREACH g = group_controls.values %]
|
||||||
<b>[% g.name FILTER html %]:</b>
|
<b>[% g.group.name FILTER html %]:</b>
|
||||||
[% IF g.isactive %]
|
[% IF g.group.isactive %]
|
||||||
[% g.membercontrol FILTER html %]/
|
[% g.membercontrol FILTER html %]/
|
||||||
[% g.othercontrol FILTER html %]
|
[% g.othercontrol FILTER html %]
|
||||||
[% IF g.entry %], ENTRY[% END %]
|
[% IF g.entry %], ENTRY[% END %]
|
||||||
|
@ -122,32 +123,21 @@ versions:</a>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th align="right">[% terms.Bugs %]:</th>
|
<th align="right">[% terms.Bugs %]:</th>
|
||||||
<td>[% bug_count FILTER html %]</td>
|
<td><a href="buglist.cgi?product=[% product.name FILTER url_quote %]">
|
||||||
|
[% product.bug_count FILTER html %]</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<input type="hidden" name="productold"
|
<input type="hidden" name="product_old_name"
|
||||||
value="[% product.name FILTER html %]">
|
value="[% product.name FILTER html %]">
|
||||||
<input type="hidden" name="descriptionold"
|
|
||||||
value="[% product.description FILTER html %]">
|
|
||||||
<input type="hidden" name="milestoneurlold"
|
|
||||||
value="[% product.milestoneurl FILTER html %]">
|
|
||||||
<input type="hidden" name="disallownewold"
|
|
||||||
value="[% product.disallownew FILTER html %]">
|
|
||||||
<input type="hidden" name="votesperuserold"
|
|
||||||
value="[% product.votesperuser FILTER html %]">
|
|
||||||
<input type="hidden" name="maxvotesperbugold"
|
|
||||||
value="[% product.maxvotesperbug FILTER html %]">
|
|
||||||
<input type="hidden" name="votestoconfirmold"
|
|
||||||
value="[% product.votestoconfirm FILTER html %]">
|
|
||||||
<input type="hidden" name="defaultmilestoneold"
|
|
||||||
value="[% product.defaultmilestone FILTER html %]">
|
|
||||||
<input type="hidden" name="action" value="update">
|
<input type="hidden" name="action" value="update">
|
||||||
<input type="hidden" name="classification"
|
<input type="hidden" name="classification"
|
||||||
value="[% classification FILTER html %]">
|
value="[% classification.name FILTER html %]">
|
||||||
<input type="submit" name="submit" value="Update">
|
<input type="submit" name="submit" value="Update">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
[% PROCESS "admin/products/footer.html.tmpl" no_add_product_link = 1 %]
|
[% PROCESS "admin/products/footer.html.tmpl"
|
||||||
|
no_add_product_link = 1
|
||||||
|
no_edit_product_link = 1 %]
|
||||||
|
|
||||||
[% PROCESS global/footer.html.tmpl %]
|
[% PROCESS global/footer.html.tmpl %]
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# name: string; the name of the product
|
# product: Bugzilla::Product Object; the product
|
||||||
#
|
#
|
||||||
# classification: string; If classifications are enabled, then this is
|
# classification: Bugzilla::Classification object ; If classifications
|
||||||
# the currently selected classification
|
# are enabled, then this is the currently
|
||||||
|
# selected classification
|
||||||
#
|
#
|
||||||
# no_XXX_link: boolean; if defined, then don't show the corresponding
|
# no_XXX_link: boolean; if defined, then don't show the corresponding
|
||||||
# link. Supported parameters are:
|
# link. Supported parameters are:
|
||||||
|
@ -30,13 +31,13 @@
|
||||||
|
|
||||||
[% IF Param('useclassification') && classification %]
|
[% IF Param('useclassification') && classification %]
|
||||||
[% classification_url_part = BLOCK %]&classification=
|
[% classification_url_part = BLOCK %]&classification=
|
||||||
[%- classification FILTER url_quote %]
|
[%- classification.name FILTER url_quote %]
|
||||||
[% END %]
|
[% END %]
|
||||||
[% classification_url_part_start = BLOCK %]classification=
|
[% classification_url_part_start = BLOCK %]classification=
|
||||||
[%- classification FILTER url_quote %]
|
[%- classification.name FILTER url_quote %]
|
||||||
[% END %]
|
[% END %]
|
||||||
[% classification_text = BLOCK %]
|
[% classification_text = BLOCK %]
|
||||||
of classification '[% classification FILTER html %]'
|
of classification '[% classification.name FILTER html %]'
|
||||||
[% END %]
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
@ -51,20 +52,22 @@
|
||||||
classification if they are enabled, but I'm just being paranoid %]
|
classification if they are enabled, but I'm just being paranoid %]
|
||||||
[% IF Param('useclassification') && classification %]
|
[% IF Param('useclassification') && classification %]
|
||||||
(<a title="Add a product to classification '
|
(<a title="Add a product to classification '
|
||||||
[%- classification FILTER html %]'"
|
[%- classification.name FILTER html %]'"
|
||||||
href="editproducts.cgi?action=add
|
href="editproducts.cgi?action=add
|
||||||
[%- classification_url_part %]">to
|
[%- classification_url_part %]">to
|
||||||
classification '[% classification FILTER html %]'</a>)
|
classification '[% classification.name FILTER html %]'
|
||||||
|
</a>)
|
||||||
[% END %].
|
[% END %].
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF name && !no_edit_product_link %]
|
[% IF product && !no_edit_product_link %]
|
||||||
Edit product <a
|
Edit product <a
|
||||||
title="Edit Product '[% name FILTER html %]'
|
title="Edit Product '[% product.name FILTER html %]'
|
||||||
[% classification_text %]"
|
[%- classification_text %]"
|
||||||
href="editproducts.cgi?action=edit&product=
|
href="editproducts.cgi?action=edit&product=
|
||||||
[%- name FILTER url_quote %][% classification_url_part %]">
|
[%- product.name FILTER url_quote %]
|
||||||
'[% name FILTER html %]'</a>.
|
[%- classification_url_part %]">
|
||||||
|
'[% product.name FILTER html %]'</a>.
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +83,7 @@
|
||||||
[% IF Param('useclassification') && classification %]
|
[% IF Param('useclassification') && classification %]
|
||||||
Edit classification <a href="editclassifications.cgi?action=edit
|
Edit classification <a href="editclassifications.cgi?action=edit
|
||||||
[%- classification_url_part %]">'
|
[%- classification_url_part %]">'
|
||||||
[%- classification FILTER html %]'</a>.
|
[%- classification.name FILTER html %]'</a>.
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,11 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% PROCESS global/variables.none.tmpl %]
|
[% PROCESS global/variables.none.tmpl %]
|
||||||
|
[% title = BLOCK %]
|
||||||
|
Confirm Group Control Change for product '[%- product.name FILTER html %]'
|
||||||
|
[% END %]
|
||||||
|
|
||||||
[% PROCESS global/header.html.tmpl title="Confirm Group Control Change for product \'$product\'" %]
|
[% PROCESS global/header.html.tmpl title = title %]
|
||||||
|
|
||||||
[% FOREACH group = mandatory_groups %]
|
[% FOREACH group = mandatory_groups %]
|
||||||
<P>
|
<P>
|
||||||
group '[% group.name FILTER html %]' impacts [% group.count %]
|
group '[% group.name FILTER html %]' impacts [% group.count %]
|
||||||
|
|
|
@ -21,16 +21,18 @@
|
||||||
|
|
||||||
[% PROCESS global/variables.none.tmpl %]
|
[% PROCESS global/variables.none.tmpl %]
|
||||||
|
|
||||||
[% filt_product = product FILTER html %]
|
[% title = BLOCK %]
|
||||||
[% filt_classification = classification FILTER html %]
|
Edit Group Controls for [% product.name FILTER html %]
|
||||||
|
[% END %]
|
||||||
[% PROCESS global/header.html.tmpl
|
[% PROCESS global/header.html.tmpl
|
||||||
title = "Edit Group Controls for '$filt_product'"
|
title = title
|
||||||
%]
|
%]
|
||||||
|
|
||||||
<form method="post" action="editproducts.cgi">
|
<form method="post" action="editproducts.cgi">
|
||||||
<input type="hidden" name="action" value="updategroupcontrols">
|
<input type="hidden" name="action" value="updategroupcontrols">
|
||||||
<input type="hidden" name="product" value="[% filt_product %]">
|
<input type="hidden" name="product" value="[% product.name FILTER html %]">
|
||||||
<input type="hidden" name="classification" value="[% filt_classification %]">
|
<input type="hidden" name="classification"
|
||||||
|
value="[% classification.name FILTER html %]">
|
||||||
|
|
||||||
<table id="form" cellspacing="0" cellpadding="4" border="1">
|
<table id="form" cellspacing="0" cellpadding="4" border="1">
|
||||||
<tr bgcolor="#6666ff">
|
<tr bgcolor="#6666ff">
|
||||||
|
|
|
@ -18,12 +18,12 @@
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# removed_na: array of hashes; groups not applicable for the product.
|
# removed_na: array of hashes; groups not applicable for the product.
|
||||||
# added_mandatory: array of hashes; groups mandatory for the product.
|
# added_mandatory: array of hashes; groups mandatory for the product.
|
||||||
# classification: string; product classification name.
|
# classification: Bugzilla::Classification object; product classification.
|
||||||
# product: string; name of the product.
|
# product: Bugzilla::Product object; the product.
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% title = BLOCK %]
|
[% title = BLOCK %]
|
||||||
Update group access controls for [% product FILTER html %]
|
Update group access controls for [% product.name FILTER html %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% PROCESS global/header.html.tmpl
|
[% PROCESS global/header.html.tmpl
|
||||||
|
@ -48,6 +48,6 @@
|
||||||
|
|
||||||
Group control updates done<p>
|
Group control updates done<p>
|
||||||
|
|
||||||
[% PROCESS admin/products/footer.html.tmpl name = product %]
|
[% PROCESS admin/products/footer.html.tmpl %]
|
||||||
|
|
||||||
[% PROCESS global/footer.html.tmpl %]
|
[% PROCESS global/footer.html.tmpl %]
|
||||||
|
|
|
@ -15,19 +15,10 @@
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
# products: array of hashes having the following properties:
|
# products: array of Bugzilla::Product objects
|
||||||
# - name: string; The name of the product
|
|
||||||
# - description: string; The product description (html allowed)
|
|
||||||
# - status: boolean; Can new bugs be created for the product?
|
|
||||||
# - votesperuser: number; The number of votes a user is allowed
|
|
||||||
# in the product
|
|
||||||
# - maxvotersperbug: number; Maximum votes allowed per bug in this
|
|
||||||
# product
|
|
||||||
# - votestoconfirm: number; The number of votes that are needed to
|
|
||||||
# auto-confirm a bug in this product
|
|
||||||
# - bug_count: number; The number of bugs in this product
|
|
||||||
#
|
#
|
||||||
# classification: string; If classifications are enabled, then this is
|
# classification: Bugzilla::Classification object; If classifications
|
||||||
|
# are enabled, then this is
|
||||||
# the currently selected classification
|
# the currently selected classification
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
|
@ -35,10 +26,10 @@
|
||||||
|
|
||||||
[% IF classification %]
|
[% IF classification %]
|
||||||
[% classification_url_part = BLOCK %]&classification=
|
[% classification_url_part = BLOCK %]&classification=
|
||||||
[%- classification FILTER url_quote %]
|
[%- classification.name FILTER url_quote %]
|
||||||
[%- END %]
|
[%- END %]
|
||||||
[% classification_title = BLOCK %]
|
[% classification_title = BLOCK %]
|
||||||
in classification '[% classification FILTER html %]'
|
in classification '[% classification.name FILTER html %]'
|
||||||
[% END %]
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
@ -54,7 +45,7 @@
|
||||||
editproducts.cgi?action=del&product=%%name%%
|
editproducts.cgi?action=del&product=%%name%%
|
||||||
[%- classification_url_part %]
|
[%- classification_url_part %]
|
||||||
[% END %]
|
[% END %]
|
||||||
[% bug_count_contentlink = BLOCK %]buglist.cgi?product=%%name%%&
|
[% bug_count_contentlink = BLOCK %]buglist.cgi?product=%%name%%
|
||||||
[%- classification_url_part %][% END %]
|
[%- classification_url_part %][% END %]
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,9 +61,8 @@
|
||||||
allow_html_content => 1
|
allow_html_content => 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name => "status"
|
name => "disallow_new"
|
||||||
heading => "Open For New $terms.Bugs"
|
heading => "Open For New $terms.Bugs"
|
||||||
yesno_field => 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name => "votesperuser"
|
name => "votesperuser"
|
||||||
|
@ -95,14 +85,26 @@
|
||||||
align => 'right'
|
align => 'right'
|
||||||
contentlink => bug_count_contentlink
|
contentlink => bug_count_contentlink
|
||||||
},
|
},
|
||||||
]
|
{
|
||||||
%]
|
|
||||||
|
|
||||||
[% columns.push({
|
|
||||||
heading => "Action"
|
heading => "Action"
|
||||||
content => "Delete"
|
content => "Delete"
|
||||||
contentlink => delete_contentlink
|
contentlink => delete_contentlink
|
||||||
})
|
},
|
||||||
|
]
|
||||||
|
%]
|
||||||
|
|
||||||
|
[% overrides.disallow_new = [ {
|
||||||
|
match_value => "1"
|
||||||
|
match_field => 'disallow_new'
|
||||||
|
override_content => 1
|
||||||
|
content => "No"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match_value => 0
|
||||||
|
match_field => 'disallow_new'
|
||||||
|
override_content => 1
|
||||||
|
content => "Yes"
|
||||||
|
}]
|
||||||
%]
|
%]
|
||||||
|
|
||||||
[% PROCESS admin/table.html.tmpl
|
[% PROCESS admin/table.html.tmpl
|
||||||
|
|
|
@ -21,33 +21,10 @@
|
||||||
|
|
||||||
[%# INTERFACE:
|
[%# INTERFACE:
|
||||||
#
|
#
|
||||||
# updated_XXX : boolean; is true when the 'XXX' field has been updated.
|
# old_product : Bugzilla::Product Object; old product.
|
||||||
# old_XXX : ... string; old value of the field 'XXX'.
|
# product : Bugzilla::Product Object; new product.
|
||||||
# new_XXX : ... string; new value of the field 'XXX'.
|
|
||||||
#
|
#
|
||||||
# updated_product: boolean; the name of the product was updated
|
# classification: Bugzilla::Classification Object; The product classification (may be empty or missing)
|
||||||
#
|
|
||||||
# updated_description: boolean; the product description was updated
|
|
||||||
#
|
|
||||||
# updated_milestoneurl: boolean; the product milestone URL was updated
|
|
||||||
#
|
|
||||||
# updated_votesperuser: boolean; the votes per user was updated
|
|
||||||
#
|
|
||||||
# updated_maxvotesperbug: boolean; the max votes per bug was updated
|
|
||||||
#
|
|
||||||
# updated_votestoconfirm: boolean; the votes to confirm a bug was updated
|
|
||||||
#
|
|
||||||
# updated_defaultmilestone: boolean; the default milestone was updated
|
|
||||||
#
|
|
||||||
# updated_bugsubmitstatus: boolean; the open/closed for new bugs status
|
|
||||||
# was updated (no 'old_XXX' value)
|
|
||||||
#
|
|
||||||
# classification: string; The product classification (may be empty or missing)
|
|
||||||
#
|
|
||||||
# changer: string; user id of the user making the changes, used for mailing
|
|
||||||
# bug changes if necessary
|
|
||||||
#
|
|
||||||
# name: string; the product name
|
|
||||||
#
|
#
|
||||||
# checkvotes: boolean; is true if vote related fields have changed. If so,
|
# checkvotes: boolean; is true if vote related fields have changed. If so,
|
||||||
# then the following parameters will be specified:
|
# then the following parameters will be specified:
|
||||||
|
@ -62,105 +39,110 @@
|
||||||
#
|
#
|
||||||
# confirmedbugs: list of bug ids, which were confirmed by votes
|
# confirmedbugs: list of bug ids, which were confirmed by votes
|
||||||
#
|
#
|
||||||
|
# changer: string; user id of the user making the changes, used for mailing
|
||||||
|
# bug changes if necessary
|
||||||
|
#
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% IF classification %]
|
[% IF classification %]
|
||||||
[% classification_url_part = BLOCK %]&classification=
|
[% classification_url_part = BLOCK %]&classification=
|
||||||
[%- classification FILTER url_quote %]
|
[%- classification.name FILTER url_quote %]
|
||||||
[% END %]
|
[% END %]
|
||||||
[% classification_text = BLOCK %]
|
[% classification_text = BLOCK %]
|
||||||
of classification '[% classification FILTER html %]'
|
of classification '[% classification.name FILTER html %]'
|
||||||
[% END %]
|
[% END %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% title = BLOCK %]Updating Product '[% name FILTER html %]'
|
[% title = BLOCK %]Updating Product '[% product.name FILTER html %]'
|
||||||
[% classification_text FILTER none %][% END %]
|
[% classification_text FILTER none %][% END %]
|
||||||
[% PROCESS global/header.html.tmpl
|
[% PROCESS global/header.html.tmpl
|
||||||
title = title
|
title = title
|
||||||
style_urls = ['skins/standard/admin.css']
|
style_urls = ['skins/standard/admin.css']
|
||||||
%]
|
%]
|
||||||
|
[% updated = 0 %]
|
||||||
|
|
||||||
[% IF updated_product %]
|
[% IF product.name != old_product.name %]
|
||||||
<p>
|
<p>
|
||||||
Updated product name from '[% old_product FILTER html %]' to
|
Updated product name from '[% old_product.name FILTER html %]' to
|
||||||
<a href="editproducts.cgi?action=edit&product=
|
<a href="editproducts.cgi?action=edit&product=
|
||||||
[%- new_product FILTER url_quote %]
|
[%- product.name FILTER url_quote %]
|
||||||
[%- classification_url_part FILTER none %]">[% new_product FILTER html %]</a>.
|
[%- classification_url_part FILTER none %]">[% product.name FILTER html %]</a>.
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
[% IF updated_description %]
|
[% IF product.description != old_product.description %]
|
||||||
<p>
|
<p>
|
||||||
Updated description to:</p>
|
Updated description to:</p>
|
||||||
</p>
|
</p>
|
||||||
<p style="margin: 1em 3em 1em 3em">[% new_description FILTER html %]</p>
|
<p style="margin: 1em 3em 1em 3em">[% product.description FILTER html %]</p>
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF updated_bugsubmitstatus %]
|
[% IF product.disallow_new != old_product.disallow_new %]
|
||||||
<p>
|
<p>
|
||||||
Product is now
|
Product is now
|
||||||
[% IF new_bugsubmitstatus %]
|
[% IF product.disallow_new %]
|
||||||
closed to
|
closed to
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
open for
|
open for
|
||||||
[% END %]
|
[% END %]
|
||||||
new [% terms.bugs %].
|
new [% terms.bugs %].
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF updated_milestoneurl %]
|
[% IF product.milestone_url != old_product.milestone_url %]
|
||||||
<p>
|
<p>
|
||||||
Updated milestone URL
|
Updated milestone URL
|
||||||
[% IF old_milestoneurl != '' %]
|
[% IF old_product.milestone_url != '' %]
|
||||||
from<br> <a href="[%- old_milestoneurl FILTER html %]">'
|
from<br> <a href="[%- old_product.milestone_url FILTER html %]">'
|
||||||
[%- old_milestoneurl FILTER html %]'</a>
|
[%- old_product.milestone_url FILTER html %]'</a>
|
||||||
[% END %]
|
[% END %]
|
||||||
to
|
to
|
||||||
[% IF new_milestoneurl != '' %]
|
[% IF product.milestone_url != '' %]
|
||||||
<br><a href="[%- new_milestoneurl FILTER html %]">'
|
<br><a href="[%- product.milestone_url FILTER html %]">'
|
||||||
[%- new_milestoneurl FILTER html %]'</a>.
|
[%- product.milestone_url FILTER html %]'</a>.
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
be empty.
|
be empty.
|
||||||
[% END %]
|
[% END %]
|
||||||
</p>
|
</p>
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF updated_defaultmilestone %]
|
[% IF product.default_milestone != old_product.default_milestone %]
|
||||||
<p>
|
<p>
|
||||||
Updated default milestone from '[% old_defaultmilestone FILTER html %]' to
|
Updated default milestone from '[% old_product.default_milestone FILTER html %]' to
|
||||||
'[% new_defaultmilestone FILTER html %]'.
|
'[% product.default_milestone FILTER html %]'.
|
||||||
</p>
|
</p>
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF updated_votesperuser %]
|
[% IF product.votes_per_user != old_product.votes_per_user %]
|
||||||
<p>
|
<p>
|
||||||
Updated votes per user from
|
Updated votes per user from
|
||||||
[%+ old_votesperuser FILTER html %] to
|
[%+ old_product.votes_per_user FILTER html %] to
|
||||||
[%+ new_votesperuser FILTER html %].
|
[%+ product.votes_per_user FILTER html %].
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF updated_maxvotesperbug %]
|
[% IF product.max_votes_per_bug != old_product.max_votes_per_bug %]
|
||||||
<p>
|
<p>
|
||||||
Updated maximum votes per [% terms.bug %] from
|
Updated maximum votes per [% terms.bug %] from
|
||||||
[%+ old_maxvotesperbug FILTER html %] to
|
[%+ old_product.max_votes_per_bug FILTER html %] to
|
||||||
[%+ new_maxvotesperbug FILTER html %].
|
[%+ product.max_votes_per_bug FILTER html %].
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% IF updated_votestoconfirm %]
|
[% IF product.votes_to_confirm != old_product.votes_to_confirm %]
|
||||||
<p>
|
<p>
|
||||||
Updated number of votes needed to confirm a [% terms.bug %] from
|
Updated number of votes needed to confirm a [% terms.bug %] from
|
||||||
[%+ old_votestoconfirm FILTER html %] to
|
[%+ old_product.votes_to_confirm FILTER html %] to
|
||||||
[%+ new_votestoconfirm FILTER html %].
|
[%+ product.votes_to_confirm FILTER html %].
|
||||||
|
[% updated = 1 %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[% UNLESS updated_bugsubmitstatus ||
|
[% UNLESS updated %]
|
||||||
updated_description ||
|
<p>Nothing changed for product '[% product.name FILTER html %]'.
|
||||||
updated_milestoneurl ||
|
|
||||||
updated_votesperuser ||
|
|
||||||
updated_maxvotesperbug ||
|
|
||||||
updated_votestoconfirm ||
|
|
||||||
updated_defaultmilestone ||
|
|
||||||
updated_product %]
|
|
||||||
<p>Nothing changed for product '[% name FILTER html %]'.
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
||||||
[%# Note that this display of changed votes and/or confirmed bugs is
|
[%# Note that this display of changed votes and/or confirmed bugs is
|
||||||
|
|
|
@ -506,8 +506,6 @@
|
||||||
],
|
],
|
||||||
|
|
||||||
'admin/products/groupcontrol/edit.html.tmpl' => [
|
'admin/products/groupcontrol/edit.html.tmpl' => [
|
||||||
'filt_classification',
|
|
||||||
'filt_product',
|
|
||||||
'group.bugcount',
|
'group.bugcount',
|
||||||
'group.id',
|
'group.id',
|
||||||
'const.CONTROLMAPNA',
|
'const.CONTROLMAPNA',
|
||||||
|
@ -522,7 +520,6 @@
|
||||||
|
|
||||||
'admin/products/confirm-delete.html.tmpl' => [
|
'admin/products/confirm-delete.html.tmpl' => [
|
||||||
'classification_url_part',
|
'classification_url_part',
|
||||||
'bug_count',
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'admin/products/footer.html.tmpl' => [
|
'admin/products/footer.html.tmpl' => [
|
||||||
|
|
Загрузка…
Ссылка в новой задаче